Skip to content

Commit 3eca9ab

Browse files
committed
fix review issues and clarify methods
1 parent c47e7bb commit 3eca9ab

File tree

2 files changed

+39
-37
lines changed

2 files changed

+39
-37
lines changed

src/dropdown/abstract-dropdown-view.class.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,16 @@ import { Observable } from "rxjs";
77
* A component that intends to be used within `Dropdown` must provide an implementation that extends this base class.
88
* It also must provide the base class in the `@Component` meta-data.
99
* ex: `providers: [{provide: AbstractDropdownView, useExisting: forwardRef(() => MyDropdownView)}]`
10-
*
11-
* @export
12-
* @class AbstractDropdownView
1310
*/
1411
export class AbstractDropdownView {
1512
/**
1613
* The items to be displayed in the list within the `AbstractDropDownView`.
17-
* @type {Array<ListItem>}
1814
*/
19-
@Input() set items(value: Array<ListItem> | Observable<Array<ListItem>>) {
20-
}
15+
@Input() set items(value: Array<ListItem> | Observable<Array<ListItem>>) { }
2116

22-
get items(): Array<ListItem> | Observable<Array<ListItem>> {
23-
return;
24-
}
17+
get items(): Array<ListItem> | Observable<Array<ListItem>> { return; }
2518
/**
2619
* Emits selection events to other class.
27-
* @type {EventEmitter<Object>}
2820
*/
2921
@Output() select: EventEmitter<Object>;
3022
/**
@@ -73,7 +65,7 @@ export class AbstractDropdownView {
7365
*/
7466
getCurrentElement(): HTMLElement { return; }
7567
/**
76-
* Returns the current items as an Array
68+
* Guaranteed to return the current items as an Array.
7769
*/
7870
getListItems(): Array<ListItem> { return; }
7971
/**

src/dropdown/list/dropdown-list.component.ts

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { AbstractDropdownView } from "./../abstract-dropdown-view.class";
1515
import { ListItem } from "./../list-item.interface";
1616
import { watchFocusJump } from "./../dropdowntools";
1717
import { ScrollableList } from "./../scrollable-list.directive";
18-
import { Observable, isObservable } from "rxjs";
18+
import { Observable, isObservable, Subscription } from "rxjs";
1919

2020

2121
/**
@@ -97,16 +97,16 @@ export class DropdownList implements AbstractDropdownView, AfterViewInit, OnDest
9797
*/
9898
@Input() set items (value: Array<ListItem> | Observable<Array<ListItem>>) {
9999
if (isObservable(value)) {
100-
value.subscribe(v => {
101-
this.updateList(v);
102-
});
100+
this._itemsSubscription.unsubscribe();
101+
this._itemsSubscription = value.subscribe(v => this.updateList(v));
103102
} else {
104103
this.updateList(value);
105104
}
105+
this._originalItems = value;
106106
}
107107

108108
get items(): Array<ListItem> | Observable<Array<ListItem>> {
109-
return this._items as Array<ListItem>;
109+
return this._originalItems;
110110
}
111111
/**
112112
* Template to bind to items in the `DropdownList` (optional).
@@ -151,7 +151,17 @@ export class DropdownList implements AbstractDropdownView, AfterViewInit, OnDest
151151
* Observable bound to keydown events to control filtering.
152152
*/
153153
protected focusJump;
154-
154+
/**
155+
* Tracks the current (if any) subscription to the items observable so we can clean up when the input is updated.
156+
*/
157+
protected _itemsSubscription: Subscription;
158+
/**
159+
* Used to retain the original items passed to the setter.
160+
*/
161+
protected _originalItems: Array<ListItem> | Observable<Array<ListItem>>;
162+
/**
163+
* Useful representation of the items, should be accessed via `getListItems`.
164+
*/
155165
protected _items: Array<ListItem> = [];
156166

157167
/**
@@ -165,7 +175,7 @@ export class DropdownList implements AbstractDropdownView, AfterViewInit, OnDest
165175
*/
166176
ngAfterViewInit() {
167177
this.listElementList = Array.from(this.list.nativeElement.querySelectorAll("li")) as HTMLElement[];
168-
this.index = this._items.findIndex(item => item.selected);
178+
this.index = this.getListItems().findIndex(item => item.selected);
169179
this.setupFocusObservable();
170180
}
171181

@@ -203,9 +213,9 @@ export class DropdownList implements AbstractDropdownView, AfterViewInit, OnDest
203213
*/
204214
filterBy(query = "") {
205215
if (query) {
206-
this.displayItems = this._items.filter(item => item.content.toLowerCase().includes(query.toLowerCase()));
216+
this.displayItems = this.getListItems().filter(item => item.content.toLowerCase().includes(query.toLowerCase()));
207217
} else {
208-
this.displayItems = this._items;
218+
this.displayItems = this.getListItems();
209219
}
210220
}
211221

@@ -228,18 +238,18 @@ export class DropdownList implements AbstractDropdownView, AfterViewInit, OnDest
228238
* Returns the `ListItem` that is subsequent to the selected item in the `DropdownList`.
229239
*/
230240
getNextItem(): ListItem {
231-
if (this.index < this._items.length - 1) {
241+
if (this.index < this.getListItems().length - 1) {
232242
this.index++;
233243
}
234-
return this._items[this.index];
244+
return this.getListItems()[this.index];
235245
}
236246

237247
/**
238248
* Returns `true` if the selected item is not the last item in the `DropdownList`.
239249
* TODO: standardize
240250
*/
241251
hasNextElement(): boolean {
242-
if (this.index < this._items.length - 1) {
252+
if (this.index < this.getListItems().length - 1) {
243253
return true;
244254
}
245255
return false;
@@ -249,11 +259,11 @@ export class DropdownList implements AbstractDropdownView, AfterViewInit, OnDest
249259
* Returns the `HTMLElement` for the item that is subsequent to the selected item.
250260
*/
251261
getNextElement(): HTMLElement {
252-
if (this.index < this._items.length - 1) {
262+
if (this.index < this.getListItems().length - 1) {
253263
this.index++;
254264
}
255265
let elem = this.listElementList[this.index];
256-
let item = this._items[this.index];
266+
let item = this.getListItems()[this.index];
257267
if (item.disabled) {
258268
return this.getNextElement();
259269
}
@@ -267,7 +277,7 @@ export class DropdownList implements AbstractDropdownView, AfterViewInit, OnDest
267277
if (this.index > 0) {
268278
this.index--;
269279
}
270-
return this._items[this.index];
280+
return this.getListItems()[this.index];
271281
}
272282

273283
/**
@@ -289,7 +299,7 @@ export class DropdownList implements AbstractDropdownView, AfterViewInit, OnDest
289299
this.index--;
290300
}
291301
let elem = this.listElementList[this.index];
292-
let item = this._items[this.index];
302+
let item = this.getListItems()[this.index];
293303
if (item.disabled) {
294304
return this.getPrevElement();
295305
}
@@ -301,9 +311,9 @@ export class DropdownList implements AbstractDropdownView, AfterViewInit, OnDest
301311
*/
302312
getCurrentItem(): ListItem {
303313
if (this.index < 0) {
304-
return this._items[0];
314+
return this.getListItems()[0];
305315
}
306-
return this._items[this.index];
316+
return this.getListItems()[this.index];
307317
}
308318

309319
/**
@@ -317,17 +327,17 @@ export class DropdownList implements AbstractDropdownView, AfterViewInit, OnDest
317327
}
318328

319329
/**
320-
* returns the items as an Array
330+
* Returns the items as an Array
321331
*/
322-
getListItems() {
332+
getListItems(): Array<ListItem> {
323333
return this._items;
324334
}
325335

326336
/**
327337
* Returns a list containing the selected item(s) in the `DropdownList`.
328338
*/
329339
getSelected(): ListItem[] {
330-
let selected = this._items.filter(item => item.selected);
340+
let selected = this.getListItems().filter(item => item.selected);
331341
if (selected.length === 0) {
332342
return null;
333343
}
@@ -345,7 +355,7 @@ export class DropdownList implements AbstractDropdownView, AfterViewInit, OnDest
345355
delete tempNewItem.selected;
346356
// stringify for compare
347357
tempNewItem = JSON.stringify(tempNewItem);
348-
for (let oldItem of this._items) {
358+
for (let oldItem of this.getListItems()) {
349359
let tempOldItem: string | ListItem = Object.assign({}, oldItem);
350360
delete tempOldItem.selected;
351361
tempOldItem = JSON.stringify(tempOldItem);
@@ -361,14 +371,14 @@ export class DropdownList implements AbstractDropdownView, AfterViewInit, OnDest
361371
}
362372

363373
/**
364-
* Initalizes focus in the list, effectivly a wrapper for `getCurrentElement().focus()`
374+
* Initializes focus in the list, effectively a wrapper for `getCurrentElement().focus()`
365375
*/
366376
initFocus() {
367377
this.getCurrentElement().focus();
368378
}
369379

370380
/**
371-
* Manages the keyboard accessiblity for navigation and selection within a `DropdownList`.
381+
* Manages the keyboard accessibility for navigation and selection within a `DropdownList`.
372382
*/
373383
doKeyDown(event: KeyboardEvent, item: ListItem) {
374384
// "Spacebar", "Down", and "Up" are IE specific values
@@ -400,7 +410,7 @@ export class DropdownList implements AbstractDropdownView, AfterViewInit, OnDest
400410
if (this.type === "single") {
401411
item.selected = true;
402412
// reset the selection
403-
for (let otherItem of this._items) {
413+
for (let otherItem of this.getListItems()) {
404414
if (item !== otherItem) { otherItem.selected = false; }
405415
}
406416

@@ -410,7 +420,7 @@ export class DropdownList implements AbstractDropdownView, AfterViewInit, OnDest
410420
// emit an array of selected items
411421
this.select.emit(this.getSelected());
412422
}
413-
this.index = this._items.indexOf(item);
423+
this.index = this.getListItems().indexOf(item);
414424
}
415425
}
416426

0 commit comments

Comments
 (0)