@@ -15,7 +15,7 @@ import { AbstractDropdownView } from "./../abstract-dropdown-view.class";
1515import { ListItem } from "./../list-item.interface" ;
1616import { watchFocusJump } from "./../dropdowntools" ;
1717import { 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