@rishavtandon93/ng-select-aria
Version:
Angular ng-select - All in One UI Select, Multiselect and Autocomplete
90 lines (77 loc) • 3.15 kB
text/typescript
import { NgOption } from './ng-select.types';
export type SelectionModelFactory = () => SelectionModel;
export function DefaultSelectionModelFactory() {
return new DefaultSelectionModel();
}
export interface SelectionModel {
value: NgOption[];
select(item: NgOption, multiple: boolean, selectableGroupAsModel: boolean);
unselect(item: NgOption, multiple: boolean);
clear(keepDisabled: boolean);
}
export class DefaultSelectionModel implements SelectionModel {
private _selected: NgOption[] = [];
get value(): NgOption[] {
return this._selected;
}
select(item: NgOption, multiple: boolean, groupAsModel: boolean) {
item.selected = true;
if (!item.children || (!multiple && groupAsModel)) {
this._selected.push(item);
}
if (multiple) {
if (item.parent) {
const childrenCount = item.parent.children.length;
const selectedCount = item.parent.children.filter(x => x.selected).length;
item.parent.selected = childrenCount === selectedCount;
} else if (item.children) {
this._setChildrenSelectedState(item.children, true);
this._removeChildren(item);
if (groupAsModel && this._activeChildren(item)) {
this._selected = [...this._selected.filter(x => x.parent !== item), item]
} else {
this._selected = [...this._selected, ...item.children.filter(x => !x.disabled)];
}
}
}
}
unselect(item: NgOption, multiple: boolean) {
this._selected = this._selected.filter(x => x !== item);
item.selected = false;
if (multiple) {
if (item.parent && item.parent.selected) {
const children = item.parent.children;
this._removeParent(item.parent);
this._removeChildren(item.parent);
this._selected.push(...children.filter(x => x !== item && !x.disabled));
item.parent.selected = false;
} else if (item.children) {
this._setChildrenSelectedState(item.children, false);
this._removeChildren(item);
}
}
}
clear(keepDisabled: boolean) {
this._selected = keepDisabled ? this._selected.filter(x => x.disabled) : [];
}
private _setChildrenSelectedState(children: NgOption[], selected: boolean) {
for (const child of children) {
if (child.disabled) {
continue;
}
child.selected = selected;
}
}
private _removeChildren(parent: NgOption) {
this._selected = [
...this._selected.filter(x => x.parent !== parent),
...parent.children.filter(x => x.parent === parent && x.disabled && x.selected)
];
}
private _removeParent(parent: NgOption) {
this._selected = this._selected.filter(x => x !== parent)
}
private _activeChildren(item: NgOption): boolean {
return item.children.every(x => !x.disabled || x.selected);
}
}