@angular/cdk
Version:
Angular Material Component Development Kit
151 lines (148 loc) • 4.39 kB
JavaScript
import { Subject } from 'rxjs';
class SelectionModel {
_multiple;
_emitChanges;
compareWith;
_selection = new Set();
_deselectedToEmit = [];
_selectedToEmit = [];
_selected;
get selected() {
if (!this._selected) {
this._selected = Array.from(this._selection.values());
}
return this._selected;
}
changed = new Subject();
constructor(_multiple = false, initiallySelectedValues, _emitChanges = true, compareWith) {
this._multiple = _multiple;
this._emitChanges = _emitChanges;
this.compareWith = compareWith;
if (initiallySelectedValues && initiallySelectedValues.length) {
if (_multiple) {
initiallySelectedValues.forEach(value => this._markSelected(value));
} else {
this._markSelected(initiallySelectedValues[0]);
}
this._selectedToEmit.length = 0;
}
}
select(...values) {
this._verifyValueAssignment(values);
values.forEach(value => this._markSelected(value));
const changed = this._hasQueuedChanges();
this._emitChangeEvent();
return changed;
}
deselect(...values) {
this._verifyValueAssignment(values);
values.forEach(value => this._unmarkSelected(value));
const changed = this._hasQueuedChanges();
this._emitChangeEvent();
return changed;
}
setSelection(...values) {
this._verifyValueAssignment(values);
const oldValues = this.selected;
const newSelectedSet = new Set(values.map(value => this._getConcreteValue(value)));
values.forEach(value => this._markSelected(value));
oldValues.filter(value => !newSelectedSet.has(this._getConcreteValue(value, newSelectedSet))).forEach(value => this._unmarkSelected(value));
const changed = this._hasQueuedChanges();
this._emitChangeEvent();
return changed;
}
toggle(value) {
return this.isSelected(value) ? this.deselect(value) : this.select(value);
}
clear(flushEvent = true) {
this._unmarkAll();
const changed = this._hasQueuedChanges();
if (flushEvent) {
this._emitChangeEvent();
}
return changed;
}
isSelected(value) {
return this._selection.has(this._getConcreteValue(value));
}
isEmpty() {
return this._selection.size === 0;
}
hasValue() {
return !this.isEmpty();
}
sort(predicate) {
if (this._multiple && this.selected) {
this._selected.sort(predicate);
}
}
isMultipleSelection() {
return this._multiple;
}
_emitChangeEvent() {
this._selected = null;
if (this._selectedToEmit.length || this._deselectedToEmit.length) {
this.changed.next({
source: this,
added: this._selectedToEmit,
removed: this._deselectedToEmit
});
this._deselectedToEmit = [];
this._selectedToEmit = [];
}
}
_markSelected(value) {
value = this._getConcreteValue(value);
if (!this.isSelected(value)) {
if (!this._multiple) {
this._unmarkAll();
}
if (!this.isSelected(value)) {
this._selection.add(value);
}
if (this._emitChanges) {
this._selectedToEmit.push(value);
}
}
}
_unmarkSelected(value) {
value = this._getConcreteValue(value);
if (this.isSelected(value)) {
this._selection.delete(value);
if (this._emitChanges) {
this._deselectedToEmit.push(value);
}
}
}
_unmarkAll() {
if (!this.isEmpty()) {
this._selection.forEach(value => this._unmarkSelected(value));
}
}
_verifyValueAssignment(values) {
if (values.length > 1 && !this._multiple && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw getMultipleValuesInSingleSelectionError();
}
}
_hasQueuedChanges() {
return !!(this._deselectedToEmit.length || this._selectedToEmit.length);
}
_getConcreteValue(inputValue, selection) {
if (!this.compareWith) {
return inputValue;
} else {
selection = selection ?? this._selection;
for (let selectedValue of selection) {
if (this.compareWith(inputValue, selectedValue)) {
return selectedValue;
}
}
return inputValue;
}
}
}
function getMultipleValuesInSingleSelectionError() {
return Error('Cannot pass multiple values into SelectionModel with single-value mode.');
}
export { SelectionModel, getMultipleValuesInSingleSelectionError };
//# sourceMappingURL=_selection-model-chunk.mjs.map