@@ -10,7 +10,6 @@ import {FocusableOption, FocusKeyManager} from '@angular/cdk/a11y';
10
10
import { coerceBooleanProperty } from '@angular/cdk/coercion' ;
11
11
import { SelectionModel } from '@angular/cdk/collections' ;
12
12
import { SPACE } from '@angular/cdk/keycodes' ;
13
- import { RxChain , startWith , switchMap } from '@angular/cdk/rxjs' ;
14
13
import {
15
14
AfterContentInit ,
16
15
ChangeDetectionStrategy ,
@@ -37,8 +36,6 @@ import {
37
36
mixinDisabled ,
38
37
mixinDisableRipple ,
39
38
} from '@angular/material/core' ;
40
- import { merge } from 'rxjs/observable/merge' ;
41
- import { Subscription } from 'rxjs/Subscription' ;
42
39
43
40
44
41
/** @docs -private */
@@ -54,8 +51,6 @@ export interface MatSelectionListOptionEvent {
54
51
option : MatListOption ;
55
52
}
56
53
57
- const FOCUSED_STYLE : string = 'mat-list-item-focus' ;
58
-
59
54
/**
60
55
* Component for list-options of selection-list. Each list-option can automatically
61
56
* generate a checkbox and can put current item into the selectionModel of selection-list
@@ -69,10 +64,11 @@ const FOCUSED_STYLE: string = 'mat-list-item-focus';
69
64
'role' : 'option' ,
70
65
'class' : 'mat-list-item mat-list-option' ,
71
66
'(focus)' : '_handleFocus()' ,
72
- '(blur)' : '_handleBlur() ' ,
67
+ '(blur)' : '_hasFocus = false ' ,
73
68
'(click)' : '_handleClick()' ,
74
69
'tabindex' : '-1' ,
75
70
'[class.mat-list-item-disabled]' : 'disabled' ,
71
+ '[class.mat-list-item-focus]' : '_hasFocus' ,
76
72
'[attr.aria-selected]' : 'selected.toString()' ,
77
73
'[attr.aria-disabled]' : 'disabled.toString()' ,
78
74
} ,
@@ -109,18 +105,12 @@ export class MatListOption extends _MatListOptionMixinBase
109
105
get selected ( ) { return this . _selected ; }
110
106
set selected ( value : boolean ) { this . _selected = coerceBooleanProperty ( value ) ; }
111
107
112
- /** Emitted when the option is focused. */
113
- onFocus = new EventEmitter < MatSelectionListOptionEvent > ( ) ;
114
-
115
108
/** Emitted when the option is selected. */
116
109
@Output ( ) selectChange = new EventEmitter < MatSelectionListOptionEvent > ( ) ;
117
110
118
111
/** Emitted when the option is deselected. */
119
112
@Output ( ) deselected = new EventEmitter < MatSelectionListOptionEvent > ( ) ;
120
113
121
- /** Emitted when the option is destroyed. */
122
- @Output ( ) destroyed = new EventEmitter < MatSelectionListOptionEvent > ( ) ;
123
-
124
114
constructor ( private _renderer : Renderer2 ,
125
115
private _element : ElementRef ,
126
116
private _changeDetector : ChangeDetectorRef ,
@@ -138,7 +128,7 @@ export class MatListOption extends _MatListOptionMixinBase
138
128
}
139
129
140
130
ngOnDestroy ( ) : void {
141
- this . destroyed . emit ( { option : this } ) ;
131
+ this . selectionList . _removeOptionFromList ( this ) ;
142
132
}
143
133
144
134
/** Toggles the selection state of the option. */
@@ -151,7 +141,6 @@ export class MatListOption extends _MatListOptionMixinBase
151
141
/** Allows for programmatic focusing of the option. */
152
142
focus ( ) : void {
153
143
this . _element . nativeElement . focus ( ) ;
154
- this . onFocus . emit ( { option : this } ) ;
155
144
}
156
145
157
146
/** Whether this list item should show a ripple effect when clicked. */
@@ -167,11 +156,7 @@ export class MatListOption extends _MatListOptionMixinBase
167
156
168
157
_handleFocus ( ) {
169
158
this . _hasFocus = true ;
170
- this . _renderer . addClass ( this . _element . nativeElement , FOCUSED_STYLE ) ;
171
- }
172
-
173
- _handleBlur ( ) {
174
- this . _renderer . removeClass ( this . _element . nativeElement , FOCUSED_STYLE ) ;
159
+ this . selectionList . _setFocusedOption ( this ) ;
175
160
}
176
161
177
162
/** Retrieves the DOM element of the component host. */
@@ -202,17 +187,11 @@ export class MatListOption extends _MatListOptionMixinBase
202
187
changeDetection : ChangeDetectionStrategy . OnPush
203
188
} )
204
189
export class MatSelectionList extends _MatSelectionListMixinBase
205
- implements FocusableOption , CanDisable , CanDisableRipple , AfterContentInit , OnDestroy {
190
+ implements FocusableOption , CanDisable , CanDisableRipple , AfterContentInit {
206
191
207
192
/** Tab index for the selection-list. */
208
193
_tabIndex = 0 ;
209
194
210
- /** Subscription to all list options' onFocus events */
211
- private _optionFocusSubscription = Subscription . EMPTY ;
212
-
213
- /** Subscription to all list options' destroy events */
214
- private _optionDestroyStream = Subscription . EMPTY ;
215
-
216
195
/** The FocusKeyManager which handles focus. */
217
196
_keyManager : FocusKeyManager < MatListOption > ;
218
197
@@ -232,14 +211,6 @@ export class MatSelectionList extends _MatSelectionListMixinBase
232
211
if ( this . disabled ) {
233
212
this . _tabIndex = - 1 ;
234
213
}
235
-
236
- this . _optionFocusSubscription = this . _onFocusSubscription ( ) ;
237
- this . _optionDestroyStream = this . _onDestroySubscription ( ) ;
238
- }
239
-
240
- ngOnDestroy ( ) : void {
241
- this . _optionDestroyStream . unsubscribe ( ) ;
242
- this . _optionFocusSubscription . unsubscribe ( ) ;
243
214
}
244
215
245
216
/** Focus the selection-list. */
@@ -265,36 +236,23 @@ export class MatSelectionList extends _MatSelectionListMixinBase
265
236
} ) ;
266
237
}
267
238
268
- /** Map all the options' destroy event subscriptions and merge them into one stream. */
269
- private _onDestroySubscription ( ) : Subscription {
270
- return RxChain . from ( this . options . changes )
271
- . call ( startWith , this . options )
272
- . call ( switchMap , ( options : MatListOption [ ] ) => {
273
- return merge ( ...options . map ( option => option . destroyed ) ) ;
274
- } ) . subscribe ( ( e : MatSelectionListOptionEvent ) => {
275
- let optionIndex : number = this . options . toArray ( ) . indexOf ( e . option ) ;
276
- if ( e . option . _hasFocus ) {
277
- // Check whether the option is the last item
278
- if ( optionIndex < this . options . length - 1 ) {
279
- this . _keyManager . setActiveItem ( optionIndex ) ;
280
- } else if ( optionIndex - 1 >= 0 ) {
281
- this . _keyManager . setActiveItem ( optionIndex - 1 ) ;
282
- }
283
- }
284
- e . option . destroyed . unsubscribe ( ) ;
285
- } ) ;
239
+ /** Sets the focused option of the selection-list. */
240
+ _setFocusedOption ( option : MatListOption ) {
241
+ this . _keyManager . updateActiveItemIndex ( this . _getOptionIndex ( option ) ) ;
286
242
}
287
243
288
- /** Map all the options' onFocus event subscriptions and merge them into one stream. */
289
- private _onFocusSubscription ( ) : Subscription {
290
- return RxChain . from ( this . options . changes )
291
- . call ( startWith , this . options )
292
- . call ( switchMap , ( options : MatListOption [ ] ) => {
293
- return merge ( ...options . map ( option => option . onFocus ) ) ;
294
- } ) . subscribe ( ( e : MatSelectionListOptionEvent ) => {
295
- let optionIndex : number = this . options . toArray ( ) . indexOf ( e . option ) ;
296
- this . _keyManager . updateActiveItemIndex ( optionIndex ) ;
297
- } ) ;
244
+ /** Removes an option from the selection list and updates the active item. */
245
+ _removeOptionFromList ( option : MatListOption ) {
246
+ if ( option . _hasFocus ) {
247
+ const optionIndex = this . _getOptionIndex ( option ) ;
248
+
249
+ // Check whether the option is the last item
250
+ if ( optionIndex > 0 ) {
251
+ this . _keyManager . setPreviousItemActive ( ) ;
252
+ } else if ( optionIndex === 0 && this . options . length > 1 ) {
253
+ this . _keyManager . setNextItemActive ( ) ;
254
+ }
255
+ }
298
256
}
299
257
300
258
/** Passes relevant key presses to our key manager. */
@@ -332,4 +290,9 @@ export class MatSelectionList extends _MatSelectionListMixinBase
332
290
private _isValidIndex ( index : number ) : boolean {
333
291
return index >= 0 && index < this . options . length ;
334
292
}
293
+
294
+ /** Returns the index of the specified list option. */
295
+ private _getOptionIndex ( option : MatListOption ) : number {
296
+ return this . options . toArray ( ) . indexOf ( option ) ;
297
+ }
335
298
}
0 commit comments