@@ -3,16 +3,17 @@ import {
3
3
ChangeDetectionStrategy ,
4
4
Component ,
5
5
ContentChildren ,
6
- ElementRef ,
7
6
Input ,
8
7
QueryList ,
9
- ViewEncapsulation
8
+ ViewEncapsulation ,
9
+ OnDestroy ,
10
10
} from '@angular/core' ;
11
11
12
12
import { MdChip } from './chip' ;
13
13
import { FocusKeyManager } from '../core/a11y/focus-key-manager' ;
14
14
import { 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' ;
16
17
17
18
/**
18
19
* 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';
30
31
template : `<div class="mat-chip-list-wrapper"><ng-content></ng-content></div>` ,
31
32
host : {
32
33
// Properties
33
- 'tabindex' : '0 ' ,
34
+ '[attr. tabindex] ' : '_tabIndex ' ,
34
35
'role' : 'listbox' ,
35
36
'[class.mat-chip-list]' : 'true' ,
36
37
@@ -45,11 +46,14 @@ import {SPACE, LEFT_ARROW, RIGHT_ARROW} from '../core/keyboard/keycodes';
45
46
encapsulation : ViewEncapsulation . None ,
46
47
changeDetection : ChangeDetectionStrategy . OnPush
47
48
} )
48
- export class MdChipList implements AfterContentInit {
49
+ export class MdChipList implements AfterContentInit , OnDestroy {
49
50
50
51
/** Track which chips we're listening to for focus/destruction. */
51
52
private _subscribed : WeakMap < MdChip , boolean > = new WeakMap ( ) ;
52
53
54
+ /** Subscription to tabbing out from the chip list. */
55
+ private _tabOutSubscription : Subscription ;
56
+
53
57
/** Whether or not the chip is selectable. */
54
58
protected _selectable : boolean = true ;
55
59
@@ -59,11 +63,19 @@ export class MdChipList implements AfterContentInit {
59
63
/** The chip components contained within this chip list. */
60
64
chips : QueryList < MdChip > ;
61
65
62
- constructor ( private _elementRef : ElementRef ) { }
66
+ /** Tab index for the chip list. */
67
+ _tabIndex = 0 ;
63
68
64
69
ngAfterContentInit ( ) : void {
65
70
this . _keyManager = new FocusKeyManager ( this . chips ) . withWrap ( ) ;
66
71
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
+
67
79
// Go ahead and subscribe all of the initial chips
68
80
this . _subscribeChips ( this . chips ) ;
69
81
@@ -73,14 +85,18 @@ export class MdChipList implements AfterContentInit {
73
85
} ) ;
74
86
}
75
87
88
+ ngOnDestroy ( ) : void {
89
+ if ( this . _tabOutSubscription ) {
90
+ this . _tabOutSubscription . unsubscribe ( ) ;
91
+ }
92
+ }
93
+
76
94
/**
77
95
* Whether or not this chip is selectable. When a chip is not selectable,
78
96
* it's selected state is always ignored.
79
97
*/
80
- @Input ( ) get selectable ( ) : boolean {
81
- return this . _selectable ;
82
- }
83
-
98
+ @Input ( )
99
+ get selectable ( ) : boolean { return this . _selectable ; }
84
100
set selectable ( value : boolean ) {
85
101
this . _selectable = coerceBooleanProperty ( value ) ;
86
102
}
0 commit comments