Skip to content

Commit ed8e07b

Browse files
committed
Added SwitchMerge
1 parent 9bd0a63 commit ed8e07b

File tree

1 file changed

+40
-60
lines changed

1 file changed

+40
-60
lines changed

src/lib/list/selection-list.ts

Lines changed: 40 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ import {Focusable} from '../core/a11y/focus-key-manager';
3232
import {MdListOption} from './list-option';
3333
import {CanDisable, mixinDisabled} from '../core/common-behaviors/disabled';
3434
import {RxChain, switchMap, first, filter} from '../core/rxjs/index';
35+
import 'rxjs/add/observable/merge';
36+
import 'rxjs/add/observable/fromEvent';
37+
import 'rxjs/add/operator/filter';
38+
import 'rxjs/add/operator/switchMap';
39+
import 'rxjs/add/observable/of';
40+
import {merge} from 'rxjs/operator/merge';
41+
import {Observable} from 'rxjs/Observable';
42+
import 'rxjs/add/operator/switchMap';
43+
import 'rxjs/add/operator/startWith';
3544

3645
export class MdSelectionListBase {}
3746
export const _MdSelectionListMixinBase = mixinDisabled(MdSelectionListBase);
@@ -59,15 +68,15 @@ export class MdSelectionList extends _MdSelectionListMixinBase
5968
/** Tab index for the selection-list. */
6069
_tabIndex = 0;
6170

62-
/** Track which options we're listening to for focus/destruction. */
63-
private _subscribed: WeakMap<MdListOption, boolean> = new WeakMap();
64-
6571
/** Subscription to tabbing out from the selection-list. */
6672
private _tabOutSubscription: Subscription;
6773

6874
/** Subscription to option changes from the selection-list. */
6975
private _optionsChangeSubscription: Subscription;
7076

77+
private _optionsChangeSubscriptionOnFocus: Subscription;
78+
private _optionsChangeSubscriptionDestory: Subscription;
79+
7180
/** The FocusKeyManager which handles focus. */
7281
_keyManager: FocusKeyManager;
7382

@@ -96,13 +105,8 @@ export class MdSelectionList extends _MdSelectionListMixinBase
96105
this._tabIndex = -1;
97106
}
98107

99-
// Go ahead and subscribe all of the initial options
100-
this._subscribeOptions(this.options);
101-
// When the list changes, re-subscribe
102-
this._optionsChangeSubscription =
103-
this.options.changes.subscribe((options: QueryList<MdListOption>) => {
104-
this._subscribeOptions(options);
105-
});
108+
this._optionsChangeSubscriptionOnFocus = this.onFocusSubscription();
109+
this._optionsChangeSubscriptionDestory = this.onDestorySubscription();
106110
}
107111

108112
ngOnDestroy(): void {
@@ -119,6 +123,32 @@ export class MdSelectionList extends _MdSelectionListMixinBase
119123
this._element.nativeElement.focus();
120124
}
121125

126+
onDestorySubscription(): Subscription {
127+
return this.options.changes.startWith(this.options).switchMap((options) => {
128+
return Observable.merge(...options.map(option => option.destroy));
129+
}).subscribe(e => {
130+
let optionIndex: number = this.options.toArray().indexOf(e.option);
131+
if (e.option._hasFocus) {
132+
// Check whether the option is the last item
133+
if (optionIndex < this.options.length - 1) {
134+
this._keyManager.setActiveItem(optionIndex);
135+
} else if (optionIndex - 1 >= 0) {
136+
this._keyManager.setActiveItem(optionIndex - 1);
137+
}
138+
}
139+
e.option.destroy.unsubscribe();
140+
});
141+
}
142+
143+
onFocusSubscription(): Subscription {
144+
return this.options.changes.startWith(this.options).switchMap((options) => {
145+
return Observable.merge(...options.map(option => option.onFocus));
146+
}).subscribe(e => {
147+
let optionIndex: number = this.options.toArray().indexOf(e.option);
148+
this._keyManager.updateActiveItemIndex(optionIndex);
149+
});
150+
}
151+
122152
/** Passes relevant key presses to our key manager. */
123153
keydown(event: KeyboardEvent) {
124154
switch (event.keyCode) {
@@ -145,56 +175,6 @@ export class MdSelectionList extends _MdSelectionListMixinBase
145175
}
146176
}
147177

148-
/**
149-
* Iterate through the list of options and add them to our list of
150-
* subscribed options.
151-
*
152-
* @param options The list of options to be subscribed.
153-
*/
154-
protected _subscribeOptions(options: QueryList<MdListOption>): void {
155-
options.forEach(option => this._addOption(option));
156-
}
157-
158-
/**
159-
* Add a specific option to our subscribed list. If the option has
160-
* already been subscribed, this ensures it is only subscribed
161-
* once.
162-
*
163-
* @param option The option to be subscribed (or checked for existing
164-
* subscription).
165-
*/
166-
protected _addOption(option: MdListOption) {
167-
// If we've already been subscribed to a parent, do nothing
168-
if (this._subscribed.has(option)) {
169-
return;
170-
}
171-
172-
// Watch for focus events outside of the keyboard navigation
173-
option.onFocus.subscribe(() => {
174-
let optionIndex: number = this.options.toArray().indexOf(option);
175-
this._keyManager.updateActiveItemIndex(optionIndex);
176-
});
177-
178-
// On destroy, remove the item from our list, and check focus
179-
option.destroy.subscribe(() => {
180-
let optionIndex: number = this.options.toArray().indexOf(option);
181-
182-
if (option._hasFocus) {
183-
// Check whether the option is the last item
184-
if (optionIndex < this.options.length - 1) {
185-
this._keyManager.setActiveItem(optionIndex);
186-
} else if (optionIndex - 1 >= 0) {
187-
this._keyManager.setActiveItem(optionIndex - 1);
188-
}
189-
}
190-
191-
this._subscribed.delete(option);
192-
option.destroy.unsubscribe();
193-
});
194-
195-
this._subscribed.set(option, true);
196-
}
197-
198178
/**
199179
* Utility to ensure all indexes are valid.
200180
*

0 commit comments

Comments
 (0)