@@ -3,16 +3,17 @@ import {
33 ChangeDetectionStrategy ,
44 Component ,
55 ContentChildren ,
6- ElementRef ,
76 Input ,
87 QueryList ,
9- ViewEncapsulation
8+ ViewEncapsulation ,
9+ OnDestroy ,
1010} from '@angular/core' ;
1111
1212import { MdChip } from './chip' ;
1313import { FocusKeyManager } from '../core/a11y/focus-key-manager' ;
1414import { coerceBooleanProperty } from '../core/coercion/boolean-property' ;
15- import { SPACE , LEFT_ARROW , RIGHT_ARROW } from '../core/keyboard/keycodes' ;
15+ import { SPACE , LEFT_ARROW , RIGHT_ARROW , TAB } from '../core/keyboard/keycodes' ;
16+ import { Subscription } from 'rxjs/Subscription' ;
1617
1718/**
1819 * A material design chips component (named ChipList for it's similarity to the List component).
@@ -30,7 +31,7 @@ import {SPACE, LEFT_ARROW, RIGHT_ARROW} from '../core/keyboard/keycodes';
3031 template : `<div class="mat-chip-list-wrapper"><ng-content></ng-content></div>` ,
3132 host : {
3233 // Properties
33- 'tabindex' : '0 ' ,
34+ '[attr. tabindex] ' : '_tabIndex ' ,
3435 'role' : 'listbox' ,
3536 '[class.mat-chip-list]' : 'true' ,
3637
@@ -45,11 +46,14 @@ import {SPACE, LEFT_ARROW, RIGHT_ARROW} from '../core/keyboard/keycodes';
4546 encapsulation : ViewEncapsulation . None ,
4647 changeDetection : ChangeDetectionStrategy . OnPush
4748} )
48- export class MdChipList implements AfterContentInit {
49+ export class MdChipList implements AfterContentInit , OnDestroy {
4950
5051 /** Track which chips we're listening to for focus/destruction. */
5152 private _subscribed : WeakMap < MdChip , boolean > = new WeakMap ( ) ;
5253
54+ /** Subscription to tabbing out from the chip list. */
55+ private _tabOutSubscription : Subscription ;
56+
5357 /** Whether or not the chip is selectable. */
5458 protected _selectable : boolean = true ;
5559
@@ -59,11 +63,19 @@ export class MdChipList implements AfterContentInit {
5963 /** The chip components contained within this chip list. */
6064 chips : QueryList < MdChip > ;
6165
62- constructor ( private _elementRef : ElementRef ) { }
66+ /** Tab index for the chip list. */
67+ _tabIndex = 0 ;
6368
6469 ngAfterContentInit ( ) : void {
6570 this . _keyManager = new FocusKeyManager ( this . chips ) . withWrap ( ) ;
6671
72+ // Prevents the chip list from capturing focus and redirecting
73+ // it back to the first chip when the user tabs out.
74+ this . _tabOutSubscription = this . _keyManager . tabOut . subscribe ( ( ) => {
75+ this . _tabIndex = - 1 ;
76+ setTimeout ( ( ) => this . _tabIndex = 0 ) ;
77+ } ) ;
78+
6779 // Go ahead and subscribe all of the initial chips
6880 this . _subscribeChips ( this . chips ) ;
6981
@@ -73,14 +85,18 @@ export class MdChipList implements AfterContentInit {
7385 } ) ;
7486 }
7587
88+ ngOnDestroy ( ) : void {
89+ if ( this . _tabOutSubscription ) {
90+ this . _tabOutSubscription . unsubscribe ( ) ;
91+ }
92+ }
93+
7694 /**
7795 * Whether or not this chip is selectable. When a chip is not selectable,
7896 * it's selected state is always ignored.
7997 */
80- @Input ( ) get selectable ( ) : boolean {
81- return this . _selectable ;
82- }
83-
98+ @Input ( )
99+ get selectable ( ) : boolean { return this . _selectable ; }
84100 set selectable ( value : boolean ) {
85101 this . _selectable = coerceBooleanProperty ( value ) ;
86102 }
0 commit comments