@@ -16,7 +16,7 @@ import {
1616} from '@angular/core' ;
1717import { NG_VALUE_ACCESSOR , ControlValueAccessor } from '@angular/forms' ;
1818import { coerceBooleanProperty } from '@angular/cdk/coercion' ;
19- import { Platform } from '@angular/cdk/platform' ;
19+ import { Platform , supportsPassiveEventListeners } from '@angular/cdk/platform' ;
2020import { fromEvent , Subject } from 'rxjs' ;
2121import { takeUntil , filter } from 'rxjs/operators' ;
2222
@@ -102,14 +102,14 @@ export class MdcCheckbox extends MDCComponent<MDCCheckboxFoundation> implements
102102
103103 _root ! : Element ;
104104
105+ private _initialized : boolean = false ;
105106 private _uniqueId : string = `mdc-checkbox-${ ++ nextUniqueId } ` ;
106107
107108 @Input ( ) id : string = this . _uniqueId ;
108109
109110 /** Returns the unique id for the visual hidden input. */
110111 get inputId ( ) : string {
111- return `${ this . id || this . _uniqueId } -input`
112- ;
112+ return `${ this . id || this . _uniqueId } -input` ;
113113 }
114114
115115 @Input ( ) name : string | null = null ;
@@ -170,7 +170,7 @@ export class MdcCheckbox extends MDCComponent<MDCCheckboxFoundation> implements
170170 }
171171 this . indeterminateChange . emit ( { source : this , indeterminate : this . _indeterminate } ) ;
172172 this . _changeDetectorRef . markForCheck ( ) ;
173- this . _foundation . handleChange ( ) ;
173+ this . _foundation ? .handleChange ( ) ;
174174 }
175175 }
176176 private _indeterminate : boolean = false ;
@@ -224,20 +224,23 @@ export class MdcCheckbox extends MDCComponent<MDCCheckboxFoundation> implements
224224 /** View to model callback called when component has been touched */
225225 _onTouched : ( ) => any = ( ) => { } ;
226226
227- getDefaultFoundation ( ) {
227+ getDefaultFoundation ( ) : any {
228+ // Do not initialize foundation until ngAfterViewInit runs
229+ if ( ! this . _initialized ) {
230+ return undefined ;
231+ }
232+
228233 const adapter : MDCCheckboxAdapter = {
229- addClass : ( className : string ) => this . _getHostElement ( ) . classList . add ( className ) ,
230- removeClass : ( className : string ) => this . _getHostElement ( ) . classList . remove ( className ) ,
234+ addClass : ( className : string ) => this . _root . classList . add ( className ) ,
235+ removeClass : ( className : string ) => this . _root . classList . remove ( className ) ,
231236 setNativeControlAttr : ( attr : string , value : string ) =>
232237 this . _inputElement . nativeElement . setAttribute ( attr , value ) ,
233- removeNativeControlAttr : ( attr : string ) =>
234- this . _inputElement . nativeElement . removeAttribute ( attr ) ,
238+ removeNativeControlAttr : ( attr : string ) => this . _inputElement . nativeElement . removeAttribute ( attr ) ,
235239 isIndeterminate : ( ) => this . indeterminate ,
236240 isChecked : ( ) => this . checked ,
237241 hasNativeControl : ( ) => true ,
238- setNativeControlDisabled : ( disabled : boolean ) =>
239- this . _inputElement . nativeElement . disabled = disabled ,
240- forceLayout : ( ) => this . _getHostElement ( ) . offsetWidth ,
242+ setNativeControlDisabled : ( disabled : boolean ) => this . _inputElement . nativeElement . disabled = disabled ,
243+ forceLayout : ( ) => ( < HTMLElement > this . _root ) . offsetWidth ,
241244 isAttachedToDOM : ( ) => true
242245 } ;
243246 return new MDCCheckboxFoundation ( adapter ) ;
@@ -253,16 +256,27 @@ export class MdcCheckbox extends MDCComponent<MDCCheckboxFoundation> implements
253256 super ( elementRef ) ;
254257
255258 this . _root = this . elementRef . nativeElement ;
256- this . ripple = this . _createRipple ( ) ;
257- this . ripple . init ( ) ;
258259
259260 if ( this . _parentFormField ) {
260261 _parentFormField . elementRef . nativeElement . classList . add ( 'mdc-form-field' ) ;
261262 }
262263 }
263264
265+ async _asyncBuildFoundation ( ) : Promise < void > {
266+ this . _foundation = this . getDefaultFoundation ( ) ;
267+ }
268+
264269 ngAfterViewInit ( ) : void {
265- this . _foundation . init ( ) ;
270+ this . _initialized = true ;
271+
272+ this . _asyncBuildFoundation ( )
273+ . then ( ( ) => {
274+ this . _foundation . init ( ) ;
275+ this . setDisabledState ( this . _inputElement . nativeElement . disabled ) ;
276+
277+ this . ripple = this . _createRipple ( ) ;
278+ this . ripple . init ( ) ;
279+ } ) ;
266280 this . _loadListeners ( ) ;
267281 }
268282
@@ -314,9 +328,13 @@ export class MdcCheckbox extends MDCComponent<MDCCheckboxFoundation> implements
314328 }
315329
316330 setDisabledState ( disabled : boolean ) : void {
317- this . _disabled = coerceBooleanProperty ( disabled ) ;
318- this . _foundation . setDisabled ( this . _disabled ) ;
319- this . _changeDetectorRef . markForCheck ( ) ;
331+ const newValue = coerceBooleanProperty ( disabled ) ;
332+
333+ if ( newValue !== this . _disabled ) {
334+ this . _disabled = newValue ;
335+ this . _foundation ?. setDisabled ( newValue ) ;
336+ this . _changeDetectorRef . markForCheck ( ) ;
337+ }
320338 }
321339
322340 private _setState ( checked ?: boolean ) : void {
@@ -344,7 +362,11 @@ export class MdcCheckbox extends MDCComponent<MDCCheckboxFoundation> implements
344362 ...MdcRipple . createAdapter ( this ) ,
345363 isSurfaceActive : ( ) => matches ( this . _inputElement . nativeElement , ':active' ) ,
346364 isUnbounded : ( ) => true ,
347- isSurfaceDisabled : ( ) => ! this . _disableRipple
365+ isSurfaceDisabled : ( ) => this . disableRipple ,
366+ deregisterInteractionHandler : ( evtType : any , handler : any ) =>
367+ this . _inputElement . nativeElement . removeEventListener ( evtType , handler , supportsPassiveEventListeners ( ) ) ,
368+ registerInteractionHandler : ( evtType : any , handler : any ) =>
369+ this . _inputElement . nativeElement . addEventListener ( evtType , handler , supportsPassiveEventListeners ( ) ) ,
348370 } ;
349371 return new MdcRipple ( this . elementRef , new MDCRippleFoundation ( adapter ) ) ;
350372 }
@@ -355,15 +377,10 @@ export class MdcCheckbox extends MDCComponent<MDCCheckboxFoundation> implements
355377 }
356378
357379 this . _ngZone . runOutsideAngular ( ( ) =>
358- fromEvent < AnimationEvent > ( this . _getHostElement ( ) , 'animationend' )
380+ fromEvent < AnimationEvent > ( this . _root , 'animationend' )
359381 . pipe ( takeUntil ( this . _destroy ) , filter ( ( e : AnimationEvent ) =>
360- e . target === this . _getHostElement ( ) ) )
382+ e . target === this . _root ) )
361383 . subscribe ( ( ) =>
362384 this . _ngZone . run ( ( ) => this . _foundation . handleAnimationEnd ( ) ) ) ) ;
363385 }
364-
365- /** Retrieves the DOM element of the component host. */
366- private _getHostElement ( ) : HTMLElement {
367- return this . elementRef . nativeElement ;
368- }
369386}
0 commit comments