diff --git a/skyux-spa-visual-tests/src/app/list-view-checklist/list-view-checklist-visual.component.html b/skyux-spa-visual-tests/src/app/list-view-checklist/list-view-checklist-visual.component.html index d5eb29c2e..9c940469a 100644 --- a/skyux-spa-visual-tests/src/app/list-view-checklist/list-view-checklist-visual.component.html +++ b/skyux-spa-visual-tests/src/app/list-view-checklist/list-view-checklist-visual.component.html @@ -1,10 +1,19 @@ + +
+ name="checklist" + [selectMode]="selectMode">
diff --git a/skyux-spa-visual-tests/src/app/list-view-checklist/list-view-checklist-visual.component.ts b/skyux-spa-visual-tests/src/app/list-view-checklist/list-view-checklist-visual.component.ts index 71ba4b90f..9ce86b7de 100644 --- a/skyux-spa-visual-tests/src/app/list-view-checklist/list-view-checklist-visual.component.ts +++ b/skyux-spa-visual-tests/src/app/list-view-checklist/list-view-checklist-visual.component.ts @@ -8,6 +8,8 @@ import { Observable } from 'rxjs/Observable'; }) export class ListViewChecklistVisualComponent { + public selectMode: string = 'multiple'; + public data: Observable> = Observable.of([ { id: '1', column1: 101, column2: 'Apple', column3: 'Anne eats apples'}, { id: '2', column1: 202, column2: 'Banana', column3: 'Ben eats bananas' }, @@ -17,4 +19,12 @@ export class ListViewChecklistVisualComponent { { id: '6', column1: 606, column2: 'Lemon', column3: 'Larry eats lemons' }, { id: '7', column1: 707, column2: 'Strawberry', column3: 'Sally eats strawberries' } ]); + + public toggleSelectMode() { + if (this.selectMode === 'multiple') { + this.selectMode = 'single'; + } else { + this.selectMode = 'multiple'; + } + } } diff --git a/skyux-spa-visual-tests/src/app/list-view-checklist/list-view-checklist.visual-spec.ts b/skyux-spa-visual-tests/src/app/list-view-checklist/list-view-checklist.visual-spec.ts index 748771bea..23bcbb922 100644 --- a/skyux-spa-visual-tests/src/app/list-view-checklist/list-view-checklist.visual-spec.ts +++ b/skyux-spa-visual-tests/src/app/list-view-checklist/list-view-checklist.visual-spec.ts @@ -26,4 +26,16 @@ describe('list-view-checklist component', () => { }); }); + + it('should display checklist view single select', () => { + return SkyVisualTest.setupTest('list-view-checklist') + .then(() => { + element(by.css('.sky-btn.sky-btn-primary')).click(); + return SkyVisualTest.compareScreenshot({ + screenshotName: 'list-view-checklist-single', + selector: '#screenshot-list-view-checklist' + }); + }); + + }); }); diff --git a/src/app/components/list-view-checklist/index.html b/src/app/components/list-view-checklist/index.html index 93f60e3b9..9bb6db118 100644 --- a/src/app/components/list-view-checklist/index.html +++ b/src/app/components/list-view-checklist/index.html @@ -6,6 +6,13 @@ + + When set to single, the checklist will only allow selection of one item in the checklist. + +

Selection mode

+
+ + + Default select mode + + +
+
+ + + Single select mode + + +
+ + + @@ -5,7 +30,8 @@ + description="column3" + [selectMode]="selectMode">
diff --git a/src/app/components/list-view-checklist/list-view-checklist-demo.component.ts b/src/app/components/list-view-checklist/list-view-checklist-demo.component.ts index ca4507b45..7987b877a 100644 --- a/src/app/components/list-view-checklist/list-view-checklist-demo.component.ts +++ b/src/app/components/list-view-checklist/list-view-checklist-demo.component.ts @@ -24,6 +24,8 @@ export class SkyListViewChecklistDemoComponent { public selectedItems: Array = []; + public selectMode: string = 'multiple'; + public selectedItemsChange(selectedMap: Map) { this.items.take(1).subscribe((items) => { this.selectedItems = items.filter((item) => { diff --git a/src/modules/list-toolbar/list-toolbar.component.html b/src/modules/list-toolbar/list-toolbar.component.html index 37f4f532e..3083036ee 100644 --- a/src/modules/list-toolbar/list-toolbar.component.html +++ b/src/modules/list-toolbar/list-toolbar.component.html @@ -37,7 +37,7 @@ - + { })); + it('should remove sort when sort selectors not available', fakeAsync(() => { + initializeToolbar(); + tick(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + tick(); + dispatcher.sortSetGlobal([]); + dispatcher.sortSetAvailable([]); + fixture.detectChanges(); + tick(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + tick(); + fixture.detectChanges(); + state.take(1).subscribe((current) => { + expect(current.toolbar.items + .filter((item) => { return item.id === 'sort-selector'; }).length).toBe(0); + }); + }); + }); + })); + it('should not display when sortSelectorEnabled is false', async(() => { component.sortEnabled = false; initializeToolbar(); diff --git a/src/modules/list-toolbar/list-toolbar.component.ts b/src/modules/list-toolbar/list-toolbar.component.ts index b003110e1..0f965ead9 100644 --- a/src/modules/list-toolbar/list-toolbar.component.ts +++ b/src/modules/list-toolbar/list-toolbar.component.ts @@ -102,6 +102,8 @@ export class SkyListToolbarComponent implements OnInit, AfterContentInit { public inlineFilterBarExpanded: boolean = false; + public hasAdditionalToolbarSection: Observable; + @ContentChildren(SkyListToolbarItemComponent) private toolbarItems: QueryList; @@ -123,6 +125,8 @@ export class SkyListToolbarComponent implements OnInit, AfterContentInit { @ViewChild('inlineFilterButton') private inlineFilterButtonTemplate: TemplateRef; + private hasSortSelectors: boolean = false; + constructor( private state: ListState, private dispatcher: ListStateDispatcher, @@ -145,6 +149,7 @@ export class SkyListToolbarComponent implements OnInit, AfterContentInit { getValue(this.toolbarType, (type: string) => { this.dispatcher.next(new ListToolbarSetTypeAction(this.toolbarType)); + }); getValue(this.sortSelectorEnabled, (sortSelectorEnabled: any) => @@ -155,22 +160,28 @@ export class SkyListToolbarComponent implements OnInit, AfterContentInit { ) ); - this.dispatcher.toolbarAddItems([ - this.toolbarType !== 'search' ? - new ListToolbarItemModel({ - id: 'search', - template: this.searchTemplate, - location: 'center' - }) : undefined, - new ListToolbarItemModel({ - id: 'sort-selector', - template: this.sortSelectorTemplate, - location: 'right' - }) - ].filter(item => item !== undefined)); - this.sortSelectors = this.getSortSelectors(); + // Initialize the sort toolbar item if necessary + this.sortSelectors.distinctUntilChanged().subscribe((currentSort) => { + + if (currentSort.length > 0 && !this.hasSortSelectors) { + this.hasSortSelectors = true; + this.dispatcher.toolbarAddItems([ + new ListToolbarItemModel({ + id: 'sort-selector', + template: this.sortSelectorTemplate, + location: 'right' + }) + ], 0); + } else if (currentSort.length < 1 && this.hasSortSelectors) { + this.hasSortSelectors = false; + this.dispatcher.toolbarRemoveItems([ + 'sort-selector' + ]); + } + }); + this.searchTextInput = this.state.map(s => s.search.searchText).distinctUntilChanged(); this.view = this.state.map(s => s.views.active).distinctUntilChanged(); @@ -183,6 +194,20 @@ export class SkyListToolbarComponent implements OnInit, AfterContentInit { this.type = this.state.map((state) => state.toolbar.type).distinctUntilChanged(); + this.type.subscribe((toolbarType) => { + if (toolbarType === 'search') { + this.dispatcher.toolbarRemoveItems(['search']); + } else { + this.dispatcher.toolbarAddItems([ + new ListToolbarItemModel({ + id: 'search', + template: this.searchTemplate, + location: 'center' + }) + ]); + } + }); + this.isSearchEnabled = this.toolbarState.map(s => s.config) .distinctUntilChanged().map(c => c.searchEnabled); @@ -194,8 +219,7 @@ export class SkyListToolbarComponent implements OnInit, AfterContentInit { }) .distinctUntilChanged() .map((filters) => { - let activeFilters = filters - .filter((f) => { + let activeFilters = filters.filter((f) => { return f.value !== '' && f.value !== undefined && f.value !== false && @@ -203,15 +227,19 @@ export class SkyListToolbarComponent implements OnInit, AfterContentInit { }); return activeFilters.length > 0; }); + + this.hasAdditionalToolbarSection = this.state.map((current) => { + return current.toolbar.items.length > 0; + }); } public ngAfterContentInit() { - this.toolbarItems.forEach(toolbarItem => + this.toolbarItems.forEach((toolbarItem) => { this.dispatcher.toolbarAddItems( [new ListToolbarItemModel(toolbarItem)], toolbarItem.index - ) - ); + ); + }); let sortModels = this.toolbarSorts.map(sort => new ListSortLabelModel( @@ -273,12 +301,13 @@ export class SkyListToolbarComponent implements OnInit, AfterContentInit { global: Array, fieldSelectors: Array ) => { + // Get sorts that are in the global that are not in the available let sorts = global.filter( g => available.filter(a => a.fieldSelector === g.fieldSelector).length === 0 ); - return [...sorts, ...available].map(sortLabels => { + let resultSortSelectors = [...sorts, ...available].map(sortLabels => { let fs = fieldSelectors.filter(f => { return f.fieldSelector === sortLabels.fieldSelector && f.descending === sortLabels.descending; @@ -293,6 +322,8 @@ export class SkyListToolbarComponent implements OnInit, AfterContentInit { selected: selected }; }); + + return resultSortSelectors; }); } diff --git a/src/modules/list-view-checklist/fixtures/list-view-checklist-toolbar.component.fixture.html b/src/modules/list-view-checklist/fixtures/list-view-checklist-toolbar.component.fixture.html index c1d2524d6..fec730087 100644 --- a/src/modules/list-view-checklist/fixtures/list-view-checklist-toolbar.component.fixture.html +++ b/src/modules/list-view-checklist/fixtures/list-view-checklist-toolbar.component.fixture.html @@ -4,6 +4,7 @@ diff --git a/src/modules/list-view-checklist/fixtures/list-view-checklist-toolbar.component.fixture.ts b/src/modules/list-view-checklist/fixtures/list-view-checklist-toolbar.component.fixture.ts index dc2c9ed2c..61f85beb6 100644 --- a/src/modules/list-view-checklist/fixtures/list-view-checklist-toolbar.component.fixture.ts +++ b/src/modules/list-view-checklist/fixtures/list-view-checklist-toolbar.component.fixture.ts @@ -9,6 +9,7 @@ import { }) export class ListViewChecklistToolbarTestComponent { public selectedItems: Map; + public selectMode: string = 'multiple'; constructor(@Inject('items') public items: any) { } diff --git a/src/modules/list-view-checklist/list-view-checklist-item.component.scss b/src/modules/list-view-checklist/list-view-checklist-item.component.scss index bdf947609..7e1f69398 100644 --- a/src/modules/list-view-checklist/list-view-checklist-item.component.scss +++ b/src/modules/list-view-checklist/list-view-checklist-item.component.scss @@ -27,4 +27,19 @@ cursor: pointer; padding-left: $sky-padding; } + + /deep/ .sky-list-view-checklist-single-button { + background-color: transparent; + border: none; + border-bottom: 1px dotted $sky-color-gray-lighter; + display: block; + text-align: left; + margin-bottom: 0; + padding: $sky-padding; + width: 100%; + cursor: pointer; + } + /deep/ .sky-list-view-checklist-single-button.sky-list-view-checklist-row-selected { + background-color: $sky-selected-color; + } } diff --git a/src/modules/list-view-checklist/list-view-checklist.component.html b/src/modules/list-view-checklist/list-view-checklist.component.html index 7b98ba363..b20456d93 100644 --- a/src/modules/list-view-checklist/list-view-checklist.component.html +++ b/src/modules/list-view-checklist/list-view-checklist.component.html @@ -1,27 +1,59 @@
- - - - {{item.label}} -
{{item.description}}
-
-
-
+
+ +
+ + + +
+
+ + + + + + {{item.label}} +
{{item.description}}
+
+
+
+
+
+
+ - - diff --git a/src/modules/list-view-checklist/list-view-checklist.component.spec.ts b/src/modules/list-view-checklist/list-view-checklist.component.spec.ts index 901711f8c..88c1664ff 100644 --- a/src/modules/list-view-checklist/list-view-checklist.component.spec.ts +++ b/src/modules/list-view-checklist/list-view-checklist.component.spec.ts @@ -377,4 +377,173 @@ describe('List View Checklist Component', () => { }); })); }); + + describe('Single select mode', () => { + let dispatcher: ListStateDispatcher, + state: ListState, + bs: BehaviorSubject>, + items: Observable>, + fixture: ComponentFixture, + nativeElement: HTMLElement, + element: DebugElement, + component: ListViewChecklistToolbarTestComponent, + itemsArray: Array; + + beforeEach(async(() => { + dispatcher = new ListStateDispatcher(); + state = new ListState(dispatcher); + + /* tslint:disable */ + itemsArray = [ + new ListItemModel('1', { column1: '1', column2: 'Apple', + column4: moment().add(1, 'minute') }), + new ListItemModel('2', { column1: '01', column2: 'Banana', + column4: moment().add(6, 'minute'), column5: 'test' }), + new ListItemModel('3', { column1: '11', column2: 'Banana', + column4: moment().add(4, 'minute') }), + new ListItemModel('4', { column1: '12', column2: 'Daikon', + column4: moment().add(2, 'minute') }), + new ListItemModel('5', { column1: '13', column2: 'Edamame', + column4: moment().add(5, 'minute') }), + new ListItemModel('6', { column1: '20', column2: 'Fig', + column4: moment().add(3, 'minute') }), + new ListItemModel('7', { column1: '21', column2: 'Grape', + column4: moment().add(7, 'minute') }) + ]; + + bs = new BehaviorSubject>(itemsArray); + items = bs.asObservable(); + + TestBed.configureTestingModule({ + declarations: [ + ListViewChecklistToolbarTestComponent + ], + imports: [ + SkyListModule, + SkyListToolbarModule, + SkyListViewChecklistModule + ], + providers: [ + { provide: 'items', useValue: items } + ] + }) + .overrideComponent(SkyListComponent, { + set: { + providers: [ + { provide: ListState, useValue: state }, + { provide: ListStateDispatcher, useValue: dispatcher } + ] + } + });; + + fixture = TestBed.createComponent(ListViewChecklistToolbarTestComponent); + nativeElement = fixture.nativeElement as HTMLElement; + element = fixture.debugElement as DebugElement; + component = fixture.componentInstance; + fixture.detectChanges(); + + // always skip the first update to ListState, when state is ready + // run detectChanges once more then begin tests + state.skip(1).take(1).subscribe(() => fixture.detectChanges()); + fixture.detectChanges(); + })); + + it('should hide the select all and clear all buttons when switched to single select mode', + fakeAsync(() => { + + tick(); + fixture.detectChanges(); + let selectAllEl = nativeElement + .querySelector('.sky-list-view-checklist-select-all'); + + let clearAllEl = nativeElement + .querySelector('.sky-list-view-checklist-clear-all'); + + expect(selectAllEl).not.toBeNull(); + expect(clearAllEl).not.toBeNull(); + + component.selectMode = 'single'; + tick(); + fixture.detectChanges(); + tick(); + fixture.detectChanges(); + selectAllEl = nativeElement + .querySelector('.sky-list-view-checklist-select-all'); + + clearAllEl = nativeElement + .querySelector('.sky-list-view-checklist-clear-all'); + + expect(selectAllEl).toBeNull(); + expect(clearAllEl).toBeNull(); + + let toolbarSectionsEl = nativeElement.querySelectorAll('sky-toolbar-section'); + expect(toolbarSectionsEl.item(1).attributes['hidden']).not.toBeUndefined(); + + })); + + it('should show the correct styles for single select mode selection', fakeAsync(() => { + tick(); + fixture.detectChanges(); + let singleSelectButtonsEl + = nativeElement + .querySelectorAll('.sky-list-view-checklist-item .sky-list-view-checklist-single-button'); + + expect(singleSelectButtonsEl.length).toBe(0); + + component.selectMode = 'single'; + tick(); + fixture.detectChanges(); + tick(); + fixture.detectChanges(); + singleSelectButtonsEl + = nativeElement + .querySelectorAll('.sky-list-view-checklist-item .sky-list-view-checklist-single-button'); + + expect(singleSelectButtonsEl.length).toBe(7); + })); + + it('should clear all but the current selection on single select button click', fakeAsync(() => { + tick(); + fixture.detectChanges(); + let singleSelectButtonsEl + = nativeElement + .querySelectorAll('.sky-list-view-checklist-item .sky-list-view-checklist-single-button'); + + expect(singleSelectButtonsEl.length).toBe(0); + + component.selectMode = 'single'; + tick(); + fixture.detectChanges(); + tick(); + fixture.detectChanges(); + singleSelectButtonsEl + = nativeElement + .querySelectorAll('.sky-list-view-checklist-item .sky-list-view-checklist-single-button'); + + (singleSelectButtonsEl.item(1) as HTMLElement).click(); + tick(); + fixture.detectChanges(); + tick(); + fixture.detectChanges(); + + expect(component.selectedItems.get('1')).toBe(undefined); + expect(component.selectedItems.get('2')).toBe(true); + expect(component.selectedItems.get('3')).toBe(undefined); + expect(component.selectedItems.get('4')).toBe(undefined); + expect(component.selectedItems.get('5')).toBe(undefined); + expect(component.selectedItems.get('6')).toBe(undefined); + expect(component.selectedItems.get('7')).toBe(undefined); + + (singleSelectButtonsEl.item(0) as HTMLElement).click(); + + expect(component.selectedItems.get('1')).toBe(true); + expect(component.selectedItems.get('2')).toBe(undefined); + expect(component.selectedItems.get('3')).toBe(undefined); + expect(component.selectedItems.get('4')).toBe(undefined); + expect(component.selectedItems.get('5')).toBe(undefined); + expect(component.selectedItems.get('6')).toBe(undefined); + expect(component.selectedItems.get('7')).toBe(undefined); + + })); + }); }); diff --git a/src/modules/list-view-checklist/list-view-checklist.component.ts b/src/modules/list-view-checklist/list-view-checklist.component.ts index cf9b88fff..cd0de3087 100644 --- a/src/modules/list-view-checklist/list-view-checklist.component.ts +++ b/src/modules/list-view-checklist/list-view-checklist.component.ts @@ -92,12 +92,26 @@ export class SkyListViewChecklistComponent extends ListViewComponent implements @Input() public description: string = 'description'; + @Input() + public set selectMode(value: string) { + this._selectMode = value; + this.updateActions(); + } + + public get selectMode(): string { + return this._selectMode; + } + @ViewChild('selectAllTemplate') private selectAllTemplate: TemplateRef; @ViewChild('clearSelectionsTemplate') private clearSelectionsTemplate: TemplateRef; + private hasSelectToolbarItems = false; + + private _selectMode = 'multiple'; + constructor( state: ListState, private dispatcher: ListStateDispatcher, @@ -150,26 +164,7 @@ export class SkyListViewChecklistComponent extends ListViewComponent implements } public ngAfterViewInit() { - this.dispatcher.toolbarAddItems([ - new ListToolbarItemModel( - { - id: 'select-all', - template: this.selectAllTemplate, - location: 'right', - index: 500, - view: this.id - } - ), - new ListToolbarItemModel( - { - id: 'clear-all', - template: this.clearSelectionsTemplate, - location: 'right', - index: 500, - view: this.id - } - ) - ]); + this.updateActions(); } get items() { @@ -207,6 +202,10 @@ export class SkyListViewChecklistComponent extends ListViewComponent implements this.dispatcher.next(new ListSelectedSetItemSelectedAction(item.id, event.checked)); } + public singleSelectRowClick(item: ListItemModel) { + this.dispatcher.next(new ListSelectedSetItemsSelectedAction([item.id], true, true)); + } + public clearSelections() { this.state.map(state => state.items.items) .take(1) @@ -225,4 +224,42 @@ export class SkyListViewChecklistComponent extends ListViewComponent implements }); } + private updateActions() { + const selectAllId = 'select-all'; + const clearAllId = 'clear-all'; + + switch (this.selectMode) { + case 'single': + this.dispatcher.toolbarRemoveItems([selectAllId, clearAllId]); + this.hasSelectToolbarItems = false; + break; + default: + if (!this.hasSelectToolbarItems) { + this.dispatcher.toolbarAddItems([ + new ListToolbarItemModel( + { + id: 'select-all', + template: this.selectAllTemplate, + location: 'right', + index: 500, + view: this.id + } + ), + new ListToolbarItemModel( + { + id: 'clear-all', + template: this.clearSelectionsTemplate, + location: 'right', + index: 500, + view: this.id + } + ) + ]); + + this.hasSelectToolbarItems = true; + } + break; + } + } + } diff --git a/src/modules/list/state/list-state-action.type.ts b/src/modules/list/state/list-state-action.type.ts index 5114f0296..948eb47c7 100644 --- a/src/modules/list/state/list-state-action.type.ts +++ b/src/modules/list/state/list-state-action.type.ts @@ -15,6 +15,7 @@ import { import { ListToolbarItemsLoadAction, + ListToolbarItemsRemoveAction, ListToolbarSetExistsAction, ListToolbarSetTypeAction } from './toolbar/actions'; @@ -50,4 +51,4 @@ export type ListStateAction = ListSearchSetFieldSelectorsAction | ListSelectedSetLoadingAction | ListSelectedLoadAction | ListSelectedSetItemSelectedAction | ListSelectedSetItemsSelectedAction | ListToolbarSetTypeAction | ListSortSetFieldSelectorsAction | ListSortSetAvailableAction | ListSortSetGlobalAction | - ListFiltersUpdateAction; + ListFiltersUpdateAction | ListToolbarItemsRemoveAction; diff --git a/src/modules/list/state/list-state.rxstate.ts b/src/modules/list/state/list-state.rxstate.ts index 33e77f2fc..c6a601b9e 100644 --- a/src/modules/list/state/list-state.rxstate.ts +++ b/src/modules/list/state/list-state.rxstate.ts @@ -9,6 +9,7 @@ import { ListViewsSetActiveAction } from './views/actions'; import { ListToolbarItemsLoadAction, + ListToolbarItemsRemoveAction, ListToolbarSetExistsAction } from './toolbar/actions'; @@ -50,6 +51,10 @@ export class ListStateDispatcher extends StateDispatcher { setTimeout(() => this.next(new ListToolbarItemsLoadAction(items, index))); } + public toolbarRemoveItems(ids: string[]): void { + setTimeout(() => this.next(new ListToolbarItemsRemoveAction(ids))); + } + public searchSetFunctions(sortFunctions: ((data: any, searchText: string) => boolean)[]): void { this.next(new ListSearchSetFunctionsAction(sortFunctions)); } diff --git a/src/modules/list/state/toolbar/actions.ts b/src/modules/list/state/toolbar/actions.ts index aa36deea4..627b74183 100644 --- a/src/modules/list/state/toolbar/actions.ts +++ b/src/modules/list/state/toolbar/actions.ts @@ -1,3 +1,4 @@ export { ListToolbarItemsLoadAction } from './load.action'; +export { ListToolbarItemsRemoveAction } from './remove.action'; export { ListToolbarSetExistsAction } from './set-exists.action'; export { ListToolbarSetTypeAction } from './set-type.action'; diff --git a/src/modules/list/state/toolbar/remove.action.ts b/src/modules/list/state/toolbar/remove.action.ts new file mode 100644 index 000000000..1d5d4794c --- /dev/null +++ b/src/modules/list/state/toolbar/remove.action.ts @@ -0,0 +1,3 @@ +export class ListToolbarItemsRemoveAction { + constructor(public ids: string[]) {} +} diff --git a/src/modules/list/state/toolbar/toolbar.orchestrator.ts b/src/modules/list/state/toolbar/toolbar.orchestrator.ts index c15ed0dec..3849faa96 100644 --- a/src/modules/list/state/toolbar/toolbar.orchestrator.ts +++ b/src/modules/list/state/toolbar/toolbar.orchestrator.ts @@ -3,6 +3,7 @@ import { ListToolbarModel } from './toolbar.model'; import { ListToolbarItemModel } from './toolbar-item.model'; import { ListToolbarItemsLoadAction, + ListToolbarItemsRemoveAction, ListToolbarSetExistsAction, ListToolbarSetTypeAction } from './actions'; @@ -16,7 +17,8 @@ export class ListToolbarOrchestrator this .register(ListToolbarSetExistsAction, this.setExists) .register(ListToolbarItemsLoadAction, this.load) - .register(ListToolbarSetTypeAction, this.setType); + .register(ListToolbarSetTypeAction, this.setType) + .register(ListToolbarItemsRemoveAction, this.remove); } private setExists( @@ -54,6 +56,20 @@ export class ListToolbarOrchestrator } newModel.items = resultItems; + + return newModel; + } + + private remove( + state: ListToolbarModel, + action: ListToolbarItemsRemoveAction + ): ListToolbarModel { + const newModel = new ListToolbarModel(state); + + newModel.items = newModel.items.filter((item: ListToolbarItemModel) => { + return action.ids.indexOf(item.id) === -1; + }); + return newModel; } }