Skip to content

Commit d548245

Browse files
committed
refactor: more efficient sorting of the selected options
1 parent 1105136 commit d548245

File tree

3 files changed

+52
-16
lines changed

3 files changed

+52
-16
lines changed

src/lib/core/selection/selection.spec.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,26 @@ describe('SelectionModel', () => {
156156
});
157157
});
158158

159+
describe('disabling the change event', () => {
160+
let model: SelectionModel<any>;
161+
162+
beforeEach(() => {
163+
model = new SelectionModel(true, null, false);
164+
});
165+
166+
it('should not have an onChange stream if change events are disabled', () => {
167+
expect(model.onChange).toBeFalsy();
168+
});
169+
170+
it('should still update the select value', () => {
171+
model.select(1);
172+
expect(model.selected).toEqual([1]);
173+
174+
model.select(2);
175+
expect(model.selected).toEqual([1, 2]);
176+
});
177+
});
178+
159179
it('should be able to determine whether it is empty', () => {
160180
let model = new SelectionModel();
161181

src/lib/core/selection/selection.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,13 @@ export class SelectionModel<T> {
2828
}
2929

3030
/** Event emitted when the value has changed. */
31-
onChange: Subject<SelectionChange<T>> = new Subject();
31+
onChange: Subject<SelectionChange<T>> = this._emitChanges ? new Subject() : null;
32+
33+
constructor(
34+
private _isMulti = false,
35+
initiallySelectedValues?: T[],
36+
private _emitChanges = true) {
3237

33-
constructor(private _isMulti = false, initiallySelectedValues?: T[]) {
3438
if (initiallySelectedValues) {
3539
if (_isMulti) {
3640
initiallySelectedValues.forEach(value => this._markSelected(value));
@@ -112,8 +116,9 @@ export class SelectionModel<T> {
112116
this.onChange.next(eventData);
113117
this._deselectedToEmit = [];
114118
this._selectedToEmit = [];
115-
this._selected = null;
116119
}
120+
121+
this._selected = null;
117122
}
118123

119124
/** Selects a value. */
@@ -124,17 +129,23 @@ export class SelectionModel<T> {
124129
}
125130

126131
this._selection.add(value);
127-
this._selectedToEmit.push(value);
132+
133+
if (this._emitChanges) {
134+
this._selectedToEmit.push(value);
135+
}
128136
}
129137
}
130138

131-
/** Deselects a value. */
132-
private _unmarkSelected(value: T) {
133-
if (this.isSelected(value)) {
134-
this._selection.delete(value);
135-
this._deselectedToEmit.push(value);
136-
}
137-
}
139+
/** Deselects a value. */
140+
private _unmarkSelected(value: T) {
141+
if (this.isSelected(value)) {
142+
this._selection.delete(value);
143+
144+
if (this._emitChanges) {
145+
this._deselectedToEmit.push(value);
146+
}
147+
}
148+
}
138149

139150
/** Clears out the selected values. */
140151
private _unmarkAll() {

src/lib/select/select.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestr
289289
}
290290

291291
ngAfterContentInit() {
292-
this._selectionModel = new SelectionModel<MdOption>(this.multiple);
292+
this._selectionModel = new SelectionModel<MdOption>(this.multiple, null, false);
293293
this._initKeyManager();
294294

295295
this._changeSubscription = this.options.changes.startWith(null).subscribe(() => {
@@ -562,13 +562,13 @@ export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestr
562562

563563
if (this.multiple) {
564564
this._selectionModel.toggle(option);
565+
wasSelected ? option.deselect() : option.select();
566+
this._sortValues();
565567
} else {
566568
this._clearSelection(option);
567569
this._selectionModel.select(option);
568570
}
569571

570-
this._sortValues();
571-
572572
if (wasSelected !== this._selectionModel.isSelected(option)) {
573573
this._propagateChanges();
574574
}
@@ -580,8 +580,13 @@ export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestr
580580
*/
581581
private _sortValues(): void {
582582
if (this._multiple) {
583-
const options = this.options.toArray();
584-
this._selectionModel.sort((a, b) => options.indexOf(a) - options.indexOf(b));
583+
this._selectionModel.clear();
584+
585+
this.options.forEach(option => {
586+
if (option.selected) {
587+
this._selectionModel.select(option);
588+
}
589+
});
585590
}
586591
}
587592

0 commit comments

Comments
 (0)