@@ -245,78 +245,99 @@ export class MatChip extends _MatChipMixinBase implements AfterContentInit, Afte
245
245
protected _chipAdapter : MDCChipAdapter = {
246
246
addClass : ( className ) => this . _setMdcClass ( className , true ) ,
247
247
removeClass : ( className ) => this . _setMdcClass ( className , false ) ,
248
- hasClass : ( className ) => this . _elementRef . nativeElement . classList . contains ( className ) ,
249
- addClassToLeadingIcon : ( className ) => this . leadingIcon . setClass ( className , true ) ,
250
- removeClassFromLeadingIcon : ( className ) => this . leadingIcon . setClass ( className , false ) ,
251
- eventTargetHasClass : ( target : EventTarget | null , className : string ) => {
252
- // We need to null check the `classList`, because IE and Edge don't support it on SVG elements
253
- // and Edge seems to throw for ripple elements, because they're outside the DOM.
254
- return ( target && ( target as Element ) . classList ) ?
255
- ( target as Element ) . classList . contains ( className ) : false ;
256
- } ,
257
- notifyInteraction : ( ) => this . interaction . emit ( this . id ) ,
258
- notifySelection : ( ) => {
259
- // No-op. We call dispatchSelectionEvent ourselves in MatChipOption, because we want to
260
- // specify whether selection occurred via user input.
261
- } ,
262
- notifyNavigation : ( ) => {
263
- // TODO: This is a new feature added by MDC; consider exposing this event to users in the
264
- // future.
265
- } ,
266
- notifyTrailingIconInteraction : ( ) => this . removeIconInteraction . emit ( this . id ) ,
267
- notifyRemoval : ( ) => {
268
- this . removed . emit ( { chip : this } ) ;
269
-
270
- // When MDC removes a chip it just transitions it to `width: 0px` which means that it's still
271
- // in the DOM and it's still focusable. Make it `display: none` so users can't tab into it.
272
- this . _elementRef . nativeElement . style . display = 'none' ;
273
- } ,
274
- getComputedStyleValue : propertyName => {
275
- // This function is run when a chip is removed so it might be
276
- // invoked during server-side rendering. Add some extra checks just in case.
277
- if ( typeof window !== 'undefined' && window ) {
278
- const getComputedStyle = window . getComputedStyle ( this . _elementRef . nativeElement ) ;
279
- return getComputedStyle . getPropertyValue ( propertyName ) ;
280
- }
281
- return '' ;
282
- } ,
283
- setStyleProperty : ( propertyName : string , value : string ) => {
284
- this . _elementRef . nativeElement . style . setProperty ( propertyName , value ) ;
285
- } ,
248
+ hasClass : ( className ) =>
249
+ this . _elementRef . nativeElement . classList . contains ( className ) ,
250
+ addClassToLeadingIcon : ( className ) =>
251
+ this . leadingIcon . setClass ( className , true ) ,
252
+ removeClassFromLeadingIcon : ( className ) =>
253
+ this . leadingIcon . setClass ( className , false ) ,
254
+ eventTargetHasClass :
255
+ ( target : EventTarget | null , className : string ) => {
256
+ // We need to null check the `classList`, because IE and Edge don't
257
+ // support it on SVG elements and Edge seems to throw for ripple
258
+ // elements, because they're outside the DOM.
259
+ return ( target && ( target as Element ) . classList ) ?
260
+ ( target as Element ) . classList . contains ( className ) :
261
+ false ;
262
+ } ,
263
+ notifyInteraction : ( ) => this . _notifyInteraction ( ) ,
264
+ notifySelection :
265
+ ( ) => {
266
+ // No-op. We call dispatchSelectionEvent ourselves in MatChipOption,
267
+ // because we want to specify whether selection occurred via user
268
+ // input.
269
+ } ,
270
+ notifyNavigation : ( ) => this . _notifyNavigation ( ) ,
271
+ notifyTrailingIconInteraction : ( ) =>
272
+ this . removeIconInteraction . emit ( this . id ) ,
273
+ notifyRemoval :
274
+ ( ) => {
275
+ this . removed . emit ( { chip : this } ) ;
276
+
277
+ // When MDC removes a chip it just transitions it to `width: 0px`
278
+ // which means that it's still in the DOM and it's still focusable.
279
+ // Make it `display: none` so users can't tab into it.
280
+ this . _elementRef . nativeElement . style . display = 'none' ;
281
+ } ,
282
+ getComputedStyleValue :
283
+ propertyName => {
284
+ // This function is run when a chip is removed so it might be
285
+ // invoked during server-side rendering. Add some extra checks just in
286
+ // case.
287
+ if ( typeof window !== 'undefined' && window ) {
288
+ const getComputedStyle =
289
+ window . getComputedStyle ( this . _elementRef . nativeElement ) ;
290
+ return getComputedStyle . getPropertyValue ( propertyName ) ;
291
+ }
292
+ return '' ;
293
+ } ,
294
+ setStyleProperty :
295
+ ( propertyName : string , value : string ) => {
296
+ this . _elementRef . nativeElement . style . setProperty ( propertyName , value ) ;
297
+ } ,
286
298
hasLeadingIcon : ( ) => ! ! this . leadingIcon ,
287
- hasTrailingAction : ( ) => ! ! this . trailingIcon ,
299
+ isTrailingActionNavigable :
300
+ ( ) => {
301
+ if ( this . trailingIcon ) {
302
+ return this . trailingIcon . isNavigable ( ) ;
303
+ }
304
+ return false ;
305
+ } ,
288
306
isRTL : ( ) => ! ! this . _dir && this . _dir . value === 'rtl' ,
289
- focusPrimaryAction : ( ) => {
290
- // Angular Material MDC chips fully manage focus. TODO: Managing focus and handling keyboard
291
- // events was added by MDC after our implementation; consider consolidating.
292
- } ,
307
+ focusPrimaryAction :
308
+ ( ) => {
309
+ // Angular Material MDC chips fully manage focus. TODO: Managing focus
310
+ // and handling keyboard events was added by MDC after our
311
+ // implementation; consider consolidating.
312
+ } ,
293
313
focusTrailingAction : ( ) => { } ,
294
- setTrailingActionAttr : ( attr , value ) =>
295
- this . trailingIcon && this . trailingIcon . setAttribute ( attr , value ) ,
296
- setPrimaryActionAttr : ( name : string , value : string ) => {
297
- // MDC is currently using this method to set aria-checked on choice and filter chips,
298
- // which in the MDC templates have role="checkbox" and role="radio" respectively.
299
- // We have role="option" on those chips instead, so we do not want aria-checked.
300
- // Since we also manage the tabindex ourselves, we don't allow MDC to set it.
301
- if ( name === 'aria-checked' || name === 'tabindex' ) {
302
- return ;
303
- }
304
- this . _elementRef . nativeElement . setAttribute ( name , value ) ;
305
- } ,
314
+ removeTrailingActionFocus : ( ) => { } ,
315
+ setPrimaryActionAttr :
316
+ ( name : string , value : string ) => {
317
+ // MDC is currently using this method to set aria-checked on choice
318
+ // and filter chips, which in the MDC templates have role="checkbox"
319
+ // and role="radio" respectively. We have role="option" on those chips
320
+ // instead, so we do not want aria-checked. Since we also manage the
321
+ // tabindex ourselves, we don't allow MDC to set it.
322
+ if ( name === 'aria-checked' || name === 'tabindex' ) {
323
+ return ;
324
+ }
325
+ this . _elementRef . nativeElement . setAttribute ( name , value ) ;
326
+ } ,
306
327
// The 2 functions below are used by the MDC ripple, which we aren't using,
307
328
// so they will never be called
308
- getRootBoundingClientRect : ( ) => this . _elementRef . nativeElement . getBoundingClientRect ( ) ,
329
+ getRootBoundingClientRect : ( ) =>
330
+ this . _elementRef . nativeElement . getBoundingClientRect ( ) ,
309
331
getCheckmarkBoundingClientRect : ( ) => null ,
310
332
getAttribute : ( attr ) => this . _elementRef . nativeElement . getAttribute ( attr ) ,
311
- } ;
312
-
313
- constructor (
314
- public _changeDetectorRef : ChangeDetectorRef ,
315
- readonly _elementRef : ElementRef ,
316
- protected _ngZone : NgZone ,
317
- @Optional ( ) private _dir : Directionality ,
318
- // @breaking -change 8.0.0 `animationMode` parameter to become required.
319
- @Optional ( ) @Inject ( ANIMATION_MODULE_TYPE ) animationMode ?: string ) {
333
+ } ;
334
+
335
+ constructor (
336
+ public _changeDetectorRef : ChangeDetectorRef ,
337
+ readonly _elementRef : ElementRef , protected _ngZone : NgZone ,
338
+ @Optional ( ) private _dir : Directionality ,
339
+ // @breaking -change 8.0.0 `animationMode` parameter to become required.
340
+ @Optional ( ) @Inject ( ANIMATION_MODULE_TYPE ) animationMode ?: string ) {
320
341
super ( _elementRef ) ;
321
342
this . _chipFoundation = new MDCChipFoundation ( this . _chipAdapter ) ;
322
343
this . _animationsDisabled = animationMode === 'NoopAnimations' ;
@@ -365,7 +386,7 @@ export class MatChip extends _MatChipMixinBase implements AfterContentInit, Afte
365
386
return ;
366
387
}
367
388
368
- this . _chipFoundation . handleTrailingIconInteraction ( event ) ;
389
+ this . _chipFoundation . handleTrailingActionInteraction ( ) ;
369
390
370
391
if ( isKeyboardEvent && ! hasModifierKey ( event as KeyboardEvent ) ) {
371
392
const keyCode = ( event as KeyboardEvent ) . keyCode ;
@@ -398,8 +419,18 @@ export class MatChip extends _MatChipMixinBase implements AfterContentInit, Afte
398
419
399
420
/** Forwards interaction events to the MDC chip foundation. */
400
421
_handleInteraction ( event : MouseEvent | KeyboardEvent ) {
401
- if ( ! this . disabled ) {
402
- this . _chipFoundation . handleInteraction ( event ) ;
422
+ if ( this . disabled ) {
423
+ return ;
424
+ }
425
+
426
+ if ( event . type === 'click' ) {
427
+ this . _chipFoundation . handleClick ( ) ;
428
+ return ;
429
+ }
430
+
431
+ if ( event . type === 'keydown' ) {
432
+ this . _chipFoundation . handleKeydown ( event as KeyboardEvent ) ;
433
+ return ;
403
434
}
404
435
}
405
436
@@ -408,6 +439,15 @@ export class MatChip extends _MatChipMixinBase implements AfterContentInit, Afte
408
439
return this . disabled || this . disableRipple || this . _animationsDisabled || this . _isBasicChip ;
409
440
}
410
441
442
+ _notifyInteraction ( ) {
443
+ this . interaction . emit ( this . id ) ;
444
+ }
445
+
446
+ _notifyNavigation ( ) {
447
+ // TODO: This is a new feature added by MDC. Consider exposing it to users
448
+ // in the future.
449
+ }
450
+
411
451
static ngAcceptInputType_disabled : BooleanInput ;
412
452
static ngAcceptInputType_removable : BooleanInput ;
413
453
static ngAcceptInputType_highlighted : BooleanInput ;
0 commit comments