diff --git a/CHANGELOG.md b/CHANGELOG.md index 160c32e5e7b..e0a021a9baa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,29 @@ All notable changes for each version of this project will be documented in this ## 8.2.0 +### New theme +Ignite UI for angular now have a new theme that mimics Microsoft "Fluent" design system. +Depending on your use case you can use one of the following mixins: +`igx-fluent-theme` and `igx-fluent-dark-theme` + +We also added two new pallets that go with the new theme, `$fluent-word-palette` and `$fluent-excel-palette`. + +Next example shows how you can use the Fluent theme. + +```scss +// Light version +.fluent-word-theme { + @include igx-fluent-theme($fluent-word-palette); +} + +// Dark version +.fluent-excel-dark-theme { + @include igx-fluent-dark-theme($fluent-excel-palette); +} +``` + +For more information about the theming please read our [documentation](https://www.infragistics.com/products/ignite-ui-angular/angular/components/themes/index.html) + ### New Features - `IgxGrid`, `IgxTreeGrid`, `IgxHierarchicalGrid` - `uniqueColumnValuesStrategy` input is added. This property provides a callback for loading unique column values on demand. If this property is provided, the unique values it generates will be used by the Excel Style Filtering (instead of using the unique values from the data that is bound to the grid). @@ -102,28 +125,6 @@ All notable changes for each version of this project will be documented in this ## 8.1.0 ### New Features - -##### New theme -Ignite UI for angular now have a new theme that mimics the Microsoft Fluent design as much as possible. -In order to use the theme you have to use one of the following mixins: - `igx-fluent-theme` and `igx-fluent-dark-theme` - -We also added two new pallets that go with the new theme, `$fluent-word-palette` and `$fluent-excel-palette`. - -This is an example of how you can use the new theme. - -```scss -// Light version -.fluent-word-theme { - @include igx-fluent-theme($fluent-word-palette); -} - -// Dark version -.fluent-excel-dark-theme { - @include igx-fluent-dark-theme($fluent-excel-palette); -} -``` - - `IgxBottomNav` now supports an `igx-tab` declaration mode. When in this mode, panels declarations are not accepted and tab items' content is not rendered. - You can use this mode to apply directives on the tab items - for example to achieve routing navigation. - You are allowed to customize tab items with labels, icons and even templates. diff --git a/projects/igniteui-angular/src/lib/core/grid-selection.ts b/projects/igniteui-angular/src/lib/core/grid-selection.ts index c33c10b3c67..33bcaabeebd 100644 --- a/projects/igniteui-angular/src/lib/core/grid-selection.ts +++ b/projects/igniteui-angular/src/lib/core/grid-selection.ts @@ -559,7 +559,7 @@ export class IgxGridSelectionService { selectAllRows(event?) { const allRowIDs = this.getRowIDs(this.allData); const addedRows = allRowIDs.filter((rID) => !this.isRowSelected(rID)); - const newSelection = this.rowSelection.size ? allRowIDs.concat(this.getSelectedRows()) : addedRows; + const newSelection = this.rowSelection.size ? this.getSelectedRows().concat(addedRows) : addedRows; this.emitRowSelectionEvent(newSelection, addedRows, [], event); } diff --git a/projects/igniteui-angular/src/lib/grids/grid-base.component.ts b/projects/igniteui-angular/src/lib/grids/grid-base.component.ts index cf14f02cdbf..a3e58c8ece4 100644 --- a/projects/igniteui-angular/src/lib/grids/grid-base.component.ts +++ b/projects/igniteui-angular/src/lib/grids/grid-base.component.ts @@ -90,7 +90,7 @@ import { IgxGridColumnResizerComponent } from './grid-column-resizer.component'; import { IgxGridFilteringRowComponent } from './filtering/grid-filtering-row.component'; import { IgxDragDirective } from '../directives/drag-drop/drag-drop.directive'; import { CharSeparatedValueData } from '../services/csv/char-separated-value-data'; -import { IgxHeadSelectorDirective, IgxRowSelectorDirective } from './igx-selection.module'; +import { IgxHeadSelectorDirective, IgxRowSelectorDirective } from './igx-row-selectors.module'; import { DeprecateProperty } from '../core/deprecateDecorators'; const MINIMUM_COLUMN_WIDTH = 136; @@ -260,7 +260,6 @@ export abstract class IgxGridBaseComponent extends DisplayDensityBase implements private _locale = null; public _destroyed = false; private overlayIDs = []; - public rowSelected = false; private _hostWidth; /** @@ -1039,7 +1038,7 @@ export abstract class IgxGridBaseComponent extends DisplayDensityBase implements /** * Emitted when `IgxGridRowComponent` is selected. * ```html - * + * * ``` * ```typescript * public onCellClickChange(e){ @@ -1754,6 +1753,10 @@ export abstract class IgxGridBaseComponent extends DisplayDensityBase implements return null; } + /** + * @hidden + * @internal + */ @ContentChildren(IgxRowSelectorDirective, { read: IgxRowSelectorDirective, descendants: false }) public rowSelectorsTemplate: QueryList; diff --git a/projects/igniteui-angular/src/lib/grids/grid-common.module.ts b/projects/igniteui-angular/src/lib/grids/grid-common.module.ts index 97fdece2178..52e388356f8 100644 --- a/projects/igniteui-angular/src/lib/grids/grid-common.module.ts +++ b/projects/igniteui-angular/src/lib/grids/grid-common.module.ts @@ -67,7 +67,7 @@ import { IgxGridExcelStyleFilteringModule } from './filtering/excel-style/grid.e import { IgxGridDragSelectDirective } from './drag-select.directive'; import { IgxGridColumnResizerComponent } from './grid-column-resizer.component'; import { IgxRowDragModule } from './row-drag.directive'; -import { IgxSelectorsModule } from './igx-selection.module'; +import { IgxRowSelectorsModule } from './igx-row-selectors.module'; /** * @hidden */ @@ -166,7 +166,7 @@ import { IgxSelectorsModule } from './igx-selection.module'; IgxRowDragModule, IgxPaginatorModule, IgxGridFooterComponent, - IgxSelectorsModule + IgxRowSelectorsModule ], imports: [ CommonModule, @@ -196,7 +196,7 @@ import { IgxSelectorsModule } from './igx-selection.module'; IgxGridExcelStyleFilteringModule, IgxRowDragModule, IgxPaginatorModule, - IgxSelectorsModule + IgxRowSelectorsModule ], providers: [ IgxGridSelectionService, diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid-cell-selection.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid-cell-selection.spec.ts index 24572cff6bd..9cab45ecb44 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid-cell-selection.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid-cell-selection.spec.ts @@ -144,13 +144,12 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should select correct cells with Ctrl key and mouse drag', () => { - pending('Related to the bug 4084'); const range = { rowStart: 3, rowEnd: 2, columnStart: 'Name', columnEnd: 'ParentID' }; const firstCell = grid.getCellByColumn(1, 'ParentID'); const secondCell = grid.getCellByColumn(1, 'ID'); const thirdCell = grid.getCellByColumn(2, 'ParentID'); const expectedData = [ - { ParentID: 147, Name: 'Michael Langdon' }, + { ParentID: 147, Name: 'Monica Reyes' }, { ParentID: 847, Name: 'Laurence Johnson' }, { ParentID: 147 } ]; diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid-keyBoardNav.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid-keyBoardNav.spec.ts index 4c8afca6bea..18c01b985d6 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid-keyBoardNav.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid-keyBoardNav.spec.ts @@ -136,7 +136,6 @@ describe('IgxGrid - Keyboard navigation #grid', () => { displayContainer.dispatchEvent(event); await wait(300); - expect(firstCell.isSelected).toBeFalsy(); expect(firstCell.selected).toBeFalsy(); expect(firstCell.focused).toBeFalsy(); })); @@ -163,7 +162,7 @@ describe('IgxGrid - Keyboard navigation #grid', () => { fix.detectChanges(); expect(cell.selected).toBeTruthy(); - expect(secondRow.isSelected).toBeTruthy(); + expect(secondRow.selected).toBeTruthy(); expect(secondRowCheckbox.classList.contains('igx-checkbox--checked')).toBeTruthy(); UIInteractions.triggerKeyDownEvtUponElem('space', cell.nativeElement, true); @@ -171,7 +170,7 @@ describe('IgxGrid - Keyboard navigation #grid', () => { fix.detectChanges(); expect(cell.selected).toBeTruthy(); - expect(secondRow.isSelected).toBeFalsy(); + expect(secondRow.selected).toBeFalsy(); expect(secondRowCheckbox.classList.contains('igx-checkbox--checked')).toBeFalsy(); cell = grid.getCellByColumn(1, 'ID'); @@ -189,7 +188,7 @@ describe('IgxGrid - Keyboard navigation #grid', () => { await wait(DEBOUNCETIME); fix.detectChanges(); - expect(firstRow.isSelected).toBeTruthy(); + expect(firstRow.selected).toBeTruthy(); expect(firstRowCheckbox.classList.contains('igx-checkbox--checked')).toBeTruthy(); UIInteractions.triggerKeyDownEvtUponElem('space', cell.nativeElement, true); @@ -197,7 +196,7 @@ describe('IgxGrid - Keyboard navigation #grid', () => { fix.detectChanges(); expect(cell.selected).toBeTruthy(); - expect(firstRow.isSelected).toBeFalsy(); + expect(firstRow.selected).toBeFalsy(); expect(firstRowCheckbox.classList.contains('igx-checkbox--checked')).toBeFalsy(); UIInteractions.triggerKeyDownWithBlur('tab', cell.nativeElement, true); diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid-row-selection.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid-row-selection.spec.ts index 82d5ab40107..759d6815295 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid-row-selection.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid-row-selection.spec.ts @@ -15,13 +15,10 @@ import { SelectionWithTransactionsComponent, GridCustomSelectorsComponent } from '../../test-utils/grid-samples.spec'; -import { IgxHierarchicalGridModule } from '../hierarchical-grid/hierarchical-grid.module'; import { HelperUtils } from '../../test-utils/helper-utils.spec'; import { GridFunctions } from '../../test-utils/grid-functions.spec'; import { SampleTestData } from '../../test-utils/sample-test-data.spec'; -import { IgxHierarchicalGridCustomSelectorsComponent } from '../../test-utils/hierarhical-grid-components.spec'; -import { IgxSelectorsModule } from '../igx-selection.module'; -import { ROW_EDITING_BANNER_OVERLAY_CLASS } from '../../test-utils/tree-grid-functions.spec'; +import { IgxRowSelectorsModule } from '../igx-row-selectors.module'; const DEBOUNCETIME = 30; @@ -42,7 +39,7 @@ describe('IgxGrid - Row Selection #grid', () => { imports: [ NoopAnimationsModule, IgxGridModule, - IgxSelectorsModule + IgxRowSelectorsModule ] }) .compileComponents(); @@ -60,7 +57,7 @@ describe('IgxGrid - Row Selection #grid', () => { it('Should have checkbox on each row', (async () => { HelperUtils.verifyHeaderRowHasCheckbox(fix); - HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(fix, grid); + HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(grid); for (const row of grid.rowList.toArray()) { HelperUtils.verifyRowHasCheckbox(row.nativeElement); @@ -70,7 +67,7 @@ describe('IgxGrid - Row Selection #grid', () => { await wait(100); fix.detectChanges(); - HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(fix, grid); + HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(grid); for (const row of grid.rowList.toArray()) { HelperUtils.verifyRowHasCheckbox(row.nativeElement); @@ -109,19 +106,19 @@ describe('IgxGrid - Row Selection #grid', () => { it('Should have correct checkboxes position when scroll left', (async () => { grid.width = '300px'; fix.detectChanges(); - HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(fix, grid); + HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(grid); GridFunctions.scrollLeft(grid, 1000); await wait(100); fix.detectChanges(); - HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(fix, grid); + HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(grid); GridFunctions.scrollLeft(grid, 0); await wait(100); fix.detectChanges(); - HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(fix, grid); + HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(grid); })); it('Header checkbox should select/deselect all rows', () => { @@ -488,7 +485,7 @@ describe('IgxGrid - Row Selection #grid', () => { HelperUtils.verifyRowSelected(firstRow, false); HelperUtils.verifyHeaderRowHasCheckbox(fix, false); HelperUtils.verifyRowHasCheckbox(firstRow.nativeElement); - HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(fix, grid); + HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(grid); // Click on a row UIInteractions.simulateClickEvent(firstRow.nativeElement); @@ -651,7 +648,7 @@ describe('IgxGrid - Row Selection #grid', () => { grid = fix.componentInstance.grid; })); - it('Change RowSelection to multiple ', () => { + it('Change RowSelection to multiple ', () => { HelperUtils.verifyHeaderRowHasCheckbox(fix, false, false); HelperUtils.verifyRowHasCheckbox(grid.getRowByIndex(0).nativeElement, false, false); @@ -663,7 +660,7 @@ describe('IgxGrid - Row Selection #grid', () => { grid.rowSelection = GridSelectionMode.multiple; fix.detectChanges(); - HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(fix, grid); + HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(grid); HelperUtils.verifyRowSelected(grid.getRowByIndex(0), false, false); HelperUtils.verifyHeaderRowCheckboxState(fix); HelperUtils.verifyHeaderRowHasCheckbox(fix); @@ -683,7 +680,7 @@ describe('IgxGrid - Row Selection #grid', () => { it('Should have checkbox on each row nd do not have header checkbox', (async () => { HelperUtils.verifyHeaderRowHasCheckbox(fix, false); - HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(fix, grid); + HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(grid); for (const row of grid.rowList.toArray()) { HelperUtils.verifyRowHasCheckbox(row.nativeElement); @@ -694,7 +691,7 @@ describe('IgxGrid - Row Selection #grid', () => { fix.detectChanges(); HelperUtils.verifyHeaderRowHasCheckbox(fix, false); - HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(fix, grid); + HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(grid); for (const row of grid.rowList.toArray()) { HelperUtils.verifyRowHasCheckbox(row.nativeElement); @@ -963,7 +960,7 @@ describe('IgxGrid - Row Selection #grid', () => { HelperUtils.verifyRowSelected(firstRow, false); HelperUtils.verifyHeaderRowHasCheckbox(fix); HelperUtils.verifyRowHasCheckbox(firstRow.nativeElement); - HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(fix, grid); + HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(grid); // Click on a row UIInteractions.simulateClickEvent(firstRow.nativeElement); diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid.search.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid.search.spec.ts index 55237d07bbd..90677228689 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid.search.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid.search.spec.ts @@ -528,7 +528,6 @@ describe('IgxGrid - search API #grid', () => { }); it('Highlight should be updated when a column is hidden and there are other hidden columns', () => { - pending('Related to the bug 3691'); grid.columns[1].hidden = true; fix.detectChanges(); diff --git a/projects/igniteui-angular/src/lib/grids/grid/row-drag.directive.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/row-drag.directive.spec.ts index 1d8f0467ee0..d4349a0787a 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/row-drag.directive.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/row-drag.directive.spec.ts @@ -593,7 +593,7 @@ describe('IgxGrid - Row Drag Tests #grid', () => { const dragIndicatorElement = dragIndicatorElements[2].nativeElement; const row = dragGridRows[1]; const rowDragDirective = dragRows[1].injector.get(IgxRowDragDirective); - expect(row.isSelected).toBeTruthy(); + expect(row.selected).toBeTruthy(); const startPoint: Point = UIInteractions.getPointFromElement(dragIndicatorElement); const movePoint: Point = UIInteractions.getPointFromElement(dragGridRows[4].nativeElement); @@ -614,7 +614,7 @@ describe('IgxGrid - Row Drag Tests #grid', () => { expect(row.grid.rowDragging).toBeFalsy(); verifyRowDragEndEvent(dragGrid, row, rowDragDirective, false); expect(dropGrid.rowList.length).toEqual(1); - expect(row.isSelected).toBeTruthy(); + expect(row.selected).toBeTruthy(); })); it('should not apply selection class to ghost element when dragging selected grid row', (async () => { dragGrid.rowSelection = GridSelectionMode.multiple; @@ -624,7 +624,7 @@ describe('IgxGrid - Row Drag Tests #grid', () => { const dragIndicatorElement = dragIndicatorElements[2].nativeElement; const row = dragGridRows[1]; - expect(row.isSelected).toBeTruthy(); + expect(row.selected).toBeTruthy(); const startPoint: Point = UIInteractions.getPointFromElement(dragIndicatorElement); const movePoint: Point = UIInteractions.getPointFromElement(dragGridRows[4].nativeElement); diff --git a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/child-grid-row.component.ts b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/child-grid-row.component.ts index 02b10d24da9..2ac5c121233 100644 --- a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/child-grid-row.component.ts +++ b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/child-grid-row.component.ts @@ -13,7 +13,7 @@ import { } from '@angular/core'; import { GridBaseAPIService } from '.././api.service'; import { IgxRowIslandComponent } from './row-island.component'; -import { IgxGridComponent } from '../grid'; +import { IgxGridComponent } from '../grid/grid.component'; import { takeUntil } from 'rxjs/operators'; @Component({ diff --git a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid-base.component.ts b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid-base.component.ts index 4376e42df56..52a3677698f 100644 --- a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid-base.component.ts +++ b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid-base.component.ts @@ -9,8 +9,7 @@ import { Optional, Input, ViewChild, - TemplateRef, - ContentChild + TemplateRef } from '@angular/core'; import { IgxGridBaseComponent, IgxGridTransaction, IGridDataBindable } from '../grid-base.component'; import { GridBaseAPIService } from '../api.service'; @@ -26,8 +25,6 @@ import { IgxHierarchicalGridNavigationService } from './hierarchical-grid-naviga import { IgxGridSummaryService } from '../summaries/grid-summary.service'; import { IgxGridSelectionService, IgxGridCRUDService } from '../../core/grid-selection'; import { IgxChildGridRowComponent } from './child-grid-row.component'; -import { IgxRowSelectorDirective, IgxHeadSelectorDirective } from '../igx-selection.module'; -import { IgxCheckboxComponent } from '../../checkbox/checkbox.component'; export const IgxHierarchicalTransactionServiceFactory = { provide: IgxGridTransaction, diff --git a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.module.ts b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.module.ts index f7b19617ddb..40df18950db 100644 --- a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.module.ts +++ b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.module.ts @@ -2,7 +2,6 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { IgxChipsModule } from '../../chips/chips.module'; -import { IgxGridCommonModule } from '../grid-common.module'; import { IgxGridModule } from '../grid/grid.module'; import { IgxHierarchicalGridComponent } from './hierarchical-grid.component'; import { IgxHierarchicalRowComponent } from './hierarchical-row.component'; @@ -13,7 +12,7 @@ import { IgxHierarchicalGridCellComponent } from './hierarchical-cell.component' import { IgxHierarchicalSelectionAPIService } from './selection'; import { IgxRowIslandAPIService } from './row-island-api.service'; import { IgxSelectModule } from '../../select/index'; -import { IgxGridComponent } from '../grid'; +import { IgxGridComponent } from '../grid/grid.component'; /** * @hidden diff --git a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.selection.spec.ts b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.selection.spec.ts index 3ada1e39023..52573151ab5 100644 --- a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.selection.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.selection.spec.ts @@ -3,17 +3,18 @@ import { async, TestBed, fakeAsync } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxHierarchicalGridModule, GridSelectionMode } from './index'; import { IgxHierarchicalGridComponent } from './hierarchical-grid.component'; -import { wait } from '../../test-utils/ui-interactions.spec'; +import { wait, UIInteractions } from '../../test-utils/ui-interactions.spec'; import { IgxHierarchicalRowComponent } from './hierarchical-row.component'; import { IgxStringFilteringOperand } from '../../data-operations/filtering-condition'; import { IgxIconModule } from '../../icon'; import { IgxHierarchicalGridTestBaseComponent, IgxHierarchicalGridRowSelectionComponent, - IgxHierarchicalGridCustomSelectorsComponent + IgxHierarchicalGridCustomSelectorsComponent, + IgxHierarchicalGridRowSelectionNoTransactionsComponent } from '../../test-utils/hierarhical-grid-components.spec'; +import { IgxRowSelectorsModule } from '../igx-row-selectors.module'; import { HelperUtils } from '../../test-utils/helper-utils.spec'; -import { IgxSelectorsModule } from '../igx-selection.module'; describe('IgxHierarchicalGrid selection #hGrid', () => { configureTestSuite(); @@ -27,13 +28,14 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { declarations: [ IgxHierarchicalGridTestBaseComponent, IgxHierarchicalGridRowSelectionComponent, - IgxHierarchicalGridCustomSelectorsComponent + IgxHierarchicalGridCustomSelectorsComponent, + IgxHierarchicalGridRowSelectionNoTransactionsComponent ], imports: [ NoopAnimationsModule, IgxHierarchicalGridModule, IgxIconModule, - IgxSelectorsModule] + IgxRowSelectorsModule] }).compileComponents(); })); @@ -86,7 +88,6 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { expect(fChildCell.selected).toBeFalsy(); expect(fCell.selected).toBeTruthy(); })); - }); describe('Row Selection', () => { @@ -99,24 +100,369 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { })); it('should have checkboxes on each row', () => { + hierarchicalGrid.expandChildren = true; + fix.detectChanges(); + rowIsland1.expandChildren = true; + fix.detectChanges(); + + expect(hierarchicalGrid.rowSelection).toEqual(GridSelectionMode.multiple); HelperUtils.verifyHeaderRowHasCheckbox(fix); - HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(fix, hierarchicalGrid); + HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(hierarchicalGrid); + + for (const r of hierarchicalGrid.dataRowList.toArray()) { + HelperUtils.verifyRowHasCheckbox(r.nativeElement); + } + + let childGrid = hierarchicalGrid.hgridAPI.getChildGrids(false)[0]; + expect(childGrid.rowSelection).toBe(GridSelectionMode.single); + HelperUtils.verifyHeaderRowHasCheckbox(childGrid, false); + HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(childGrid); + + for (const r of childGrid.dataRowList.toArray()) { + HelperUtils.verifyRowHasCheckbox(r.nativeElement); + } + + childGrid = childGrid.hgridAPI.getChildGrids(false)[0]; + expect(childGrid.rowSelection).toBe(GridSelectionMode.none); + HelperUtils.verifyHeaderRowHasCheckbox(childGrid, false, false); - for (const row of hierarchicalGrid.rowList.toArray()) { - HelperUtils.verifyRowHasCheckbox(row.nativeElement); + for (const r of childGrid.dataRowList.toArray()) { + HelperUtils.verifyRowHasCheckbox(r.nativeElement, false, false); } }); - it('should retain selected row when filtering', () => { - const firstRow = hierarchicalGrid.getRowByIndex(0); - HelperUtils.clickRowCheckbox(firstRow); + it('should able to change rowSelection at runtime', () => { + hierarchicalGrid.expandChildren = true; + fix.detectChanges(); + rowIsland1.expandChildren = true; fix.detectChanges(); - hierarchicalGrid.filter('ID', '1', IgxStringFilteringOperand.instance().condition('doesNotContain'), true); + const childGridLevel1 = hierarchicalGrid.hgridAPI.getChildGrids(false)[0]; + const childGridLevel2 = childGridLevel1.hgridAPI.getChildGrids(false)[0]; + + hierarchicalGrid.selectAllRows(); + childGridLevel1.selectedRows(['00']); fix.detectChanges(); - HelperUtils.verifyRowSelected(hierarchicalGrid.getRowByIndex(0)); - HelperUtils.verifyHeaderRowCheckboxState(fix, false, true); + // Change row selection for grids + hierarchicalGrid.rowSelection = GridSelectionMode.none; + rowIsland1.rowSelection = GridSelectionMode.multiple; + rowIsland2.rowSelection = GridSelectionMode.single; + fix.detectChanges(); + + expect(hierarchicalGrid.rowSelection).toBe(GridSelectionMode.none); + expect(hierarchicalGrid.selectedRows()).toEqual([]); + HelperUtils.verifyHeaderRowHasCheckbox(hierarchicalGrid, false, false); + for (const r of hierarchicalGrid.dataRowList.toArray()) { + HelperUtils.verifyRowHasCheckbox(r.nativeElement, false, false); + } + + expect(childGridLevel1.rowSelection).toBe(GridSelectionMode.multiple); + expect(childGridLevel1.selectedRows()).toEqual([]); + HelperUtils.verifyHeaderRowHasCheckbox(childGridLevel1); + for (const r of childGridLevel1.dataRowList.toArray()) { + HelperUtils.verifyRowHasCheckbox(r.nativeElement); + } + HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(childGridLevel1); + + expect(childGridLevel2.rowSelection).toBe(GridSelectionMode.single); + expect(childGridLevel2.selectedRows()).toEqual([]); + HelperUtils.verifyHeaderRowHasCheckbox(childGridLevel2, false); + for (const r of childGridLevel2.dataRowList.toArray()) { + HelperUtils.verifyRowHasCheckbox(r.nativeElement); + } + HelperUtils.verifyHeaderAndRowCheckBoxesAlignment(childGridLevel2); + }); + + it('should able to change showRowCheckboxes at runtime', () => { + hierarchicalGrid.expandChildren = true; + fix.detectChanges(); + + hierarchicalGrid.hideRowSelectors = true; + rowIsland1.hideRowSelectors = true; + fix.detectChanges(); + + expect(hierarchicalGrid.hideRowSelectors).toBe(true); + HelperUtils.verifyHeaderRowHasCheckbox(hierarchicalGrid, false, false); + for (const r of hierarchicalGrid.dataRowList.toArray()) { + HelperUtils.verifyRowHasCheckbox(r.nativeElement, false, false); + } + + const childGridLevel1 = hierarchicalGrid.hgridAPI.getChildGrids(false)[0]; + expect(childGridLevel1.hideRowSelectors).toBe(true); + HelperUtils.verifyHeaderRowHasCheckbox(childGridLevel1, false, false); + for (const r of childGridLevel1.dataRowList.toArray()) { + HelperUtils.verifyRowHasCheckbox(r.nativeElement, false, false); + } + + hierarchicalGrid.hideRowSelectors = false; + rowIsland1.hideRowSelectors = false; + fix.detectChanges(); + + expect(hierarchicalGrid.hideRowSelectors).toBe(false); + HelperUtils.verifyHeaderRowHasCheckbox(hierarchicalGrid); + for (const r of hierarchicalGrid.dataRowList.toArray()) { + HelperUtils.verifyRowHasCheckbox(r.nativeElement); + } + + expect(childGridLevel1.hideRowSelectors).toBe(false); + HelperUtils.verifyHeaderRowHasCheckbox(childGridLevel1, false); + for (const r of childGridLevel1.dataRowList.toArray()) { + HelperUtils.verifyRowHasCheckbox(r.nativeElement); + } + }); + + it('should have fire event onRowSelectionChange', () => { + hierarchicalGrid.expandChildren = true; + fix.detectChanges(); + const childGrid = hierarchicalGrid.hgridAPI.getChildGrids(false)[0]; + const secondChildGrid = hierarchicalGrid.hgridAPI.getChildGrids(false)[1]; + const parentSpy = spyOn(hierarchicalGrid.onRowSelectionChange, 'emit').and.callThrough(); + const childSpy = spyOn(childGrid.onRowSelectionChange, 'emit').and.callThrough(); + const secondChildSpy = spyOn(secondChildGrid.onRowSelectionChange, 'emit').and.callThrough(); + const mockEvent = new MouseEvent('click'); + + // Click on a row in child grid + let row = childGrid.dataRowList.toArray()[0]; + row.nativeElement.dispatchEvent(mockEvent); + fix.detectChanges(); + + expect(secondChildSpy).toHaveBeenCalledTimes(0); + expect(parentSpy).toHaveBeenCalledTimes(0); + expect(childSpy).toHaveBeenCalledTimes(1); + expect(childSpy).toHaveBeenCalledWith({ + added: ['00'], + cancel: false, + event: mockEvent, + newSelection: ['00'], + oldSelection: [], + removed: [], + owner: childGrid + }); + + // Click on checkbox on second row + HelperUtils.getRowCheckboxDiv(childGrid.dataRowList.toArray()[1].nativeElement).dispatchEvent(mockEvent); + fix.detectChanges(); + + expect(secondChildSpy).toHaveBeenCalledTimes(0); + expect(parentSpy).toHaveBeenCalledTimes(0); + expect(childSpy).toHaveBeenCalledTimes(2); + expect(childSpy).toHaveBeenCalledWith({ + added: ['01'], + cancel: false, + event: mockEvent, + newSelection: ['01'], + oldSelection: ['00'], + removed: ['00'], + owner: childGrid + }); + + // Click on a row in parent grid + row = hierarchicalGrid.dataRowList.toArray()[1]; + row.nativeElement.dispatchEvent(mockEvent); + fix.detectChanges(); + + expect(secondChildSpy).toHaveBeenCalledTimes(0); + expect(childSpy).toHaveBeenCalledTimes(2); + expect(parentSpy).toHaveBeenCalledTimes(1); + expect(parentSpy).toHaveBeenCalledWith({ + added: ['1'], + cancel: false, + event: mockEvent, + newSelection: ['1'], + oldSelection: [], + removed: [] + }); + + // Click on a header checkbox in parent grid + HelperUtils.getRowCheckboxDiv(HelperUtils.getHeaderRow(hierarchicalGrid)).dispatchEvent(mockEvent); + fix.detectChanges(); + + expect(secondChildSpy).toHaveBeenCalledTimes(0); + expect(childSpy).toHaveBeenCalledTimes(2); + expect(parentSpy).toHaveBeenCalledTimes(2); + expect(parentSpy).toHaveBeenCalledWith({ + added: ['0', '2', '3', '4'], + cancel: false, + event: mockEvent, + newSelection: ['1', '0', '2', '3', '4'], + oldSelection: ['1'], + removed: [] + }); + }); + + it('should able to select multiple rows with Shift and click', () => { + // Expand first row + const firstRow = hierarchicalGrid.dataRowList.toArray()[0]; + firstRow.nativeElement.children[0].click(); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(firstRow, false); + + UIInteractions.simulateClickEvent(firstRow.nativeElement); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(firstRow); + expect(hierarchicalGrid.selectedRows()).toEqual(['0']); + + const fourthRow = hierarchicalGrid.dataRowList.toArray()[3]; + UIInteractions.simulateClickEvent(fourthRow.nativeElement, true); + fix.detectChanges(); + + HelperUtils.verifyRowsArraySelected( + [firstRow, hierarchicalGrid.dataRowList.toArray()[1], hierarchicalGrid.dataRowList.toArray()[2], fourthRow]); + expect(hierarchicalGrid.selectedRows()).toEqual(['0', '1', '2', '3']); + + // Verify no rows are selected in the child grid + const childGrid = hierarchicalGrid.hgridAPI.getChildGrids(false)[0]; + expect(childGrid.selectedRows()).toEqual([]); + for (const r of childGrid.dataRowList.toArray()) { + HelperUtils.verifyRowSelected(r, false); + } + }); + + it('should able to select multiple rows with Ctrl and click', () => { + // Expand first row + const firstRow = hierarchicalGrid.dataRowList.toArray()[0]; + firstRow.nativeElement.children[0].click(); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(firstRow, false); + + UIInteractions.simulateClickEvent(firstRow.nativeElement); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(firstRow); + expect(hierarchicalGrid.selectedRows()).toEqual(['0']); + + const fourthRow = hierarchicalGrid.dataRowList.toArray()[3]; + UIInteractions.simulateClickEvent(fourthRow.nativeElement, false, true); + fix.detectChanges(); + + HelperUtils.verifyRowsArraySelected([firstRow, fourthRow]); + expect(hierarchicalGrid.selectedRows()).toEqual(['0', '3']); + + // Click on a row in the child grid + const childGrid = hierarchicalGrid.hgridAPI.getChildGrids(false)[0]; + expect(childGrid.selectedRows()).toEqual([]); + + const childGridFirstRow = childGrid.dataRowList.toArray()[2]; + UIInteractions.simulateClickEvent(childGridFirstRow.nativeElement, false, true); + fix.detectChanges(); + + HelperUtils.verifyRowsArraySelected([firstRow, fourthRow]); + expect(hierarchicalGrid.selectedRows()).toEqual(['0', '3']); + HelperUtils.verifyRowSelected(childGridFirstRow); + expect(childGrid.selectedRows()).toEqual(['02']); + }); + + it('should able to select only one row when rowSelection is single', () => { + // Expand first row + hierarchicalGrid.dataRowList.toArray()[0].nativeElement.children[0].click(); + fix.detectChanges(); + + // Click on a row in the child grid + const childGrid = hierarchicalGrid.hgridAPI.getChildGrids(false)[0]; + expect(childGrid.selectedRows()).toEqual([]); + + const firstRow = childGrid.dataRowList.toArray()[0]; + const secondRow = childGrid.dataRowList.toArray()[2]; + + UIInteractions.simulateClickEvent(firstRow.nativeElement); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(firstRow); + expect(childGrid.selectedRows()).toEqual(['00']); + + // Click on second row holding Ctrl + UIInteractions.simulateClickEvent(secondRow.nativeElement, false, true); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(firstRow, false); + HelperUtils.verifyRowSelected(secondRow); + expect(childGrid.selectedRows()).toEqual(['02']); + + // Click on first row holding Shift key + UIInteractions.simulateClickEvent(firstRow.nativeElement, true); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(firstRow); + HelperUtils.verifyRowSelected(secondRow, false); + expect(childGrid.selectedRows()).toEqual(['00']); + + // Click on second row checkbox + HelperUtils.clickRowCheckbox(secondRow); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(firstRow, false); + HelperUtils.verifyRowSelected(secondRow); + expect(childGrid.selectedRows()).toEqual(['02']); + }); + + it('should able to select/deselect all rows by clicking on the header checkbox', () => { + // Set multiple selection to first row island + rowIsland1.rowSelection = GridSelectionMode.multiple; + fix.detectChanges(); + + // Expand first row + const firstRow = hierarchicalGrid.dataRowList.toArray()[0]; + firstRow.nativeElement.children[0].click(); + fix.detectChanges(); + + // Expand second row + const secondRow = hierarchicalGrid.dataRowList.toArray()[1]; + secondRow.nativeElement.children[0].click(); + fix.detectChanges(); + + // Select all rows in parent + HelperUtils.clickHeaderRowCheckbox(hierarchicalGrid); + fix.detectChanges(); + + expect(hierarchicalGrid.selectedRows()).toEqual(['0', '1', '2', '3', '4']); + HelperUtils.verifyHeaderRowCheckboxState(hierarchicalGrid, true); + + const childGrid1 = hierarchicalGrid.hgridAPI.getChildGrids(false)[0]; + const childGrid2 = hierarchicalGrid.hgridAPI.getChildGrids(false)[1]; + expect(childGrid1.selectedRows()).toEqual([]); + expect(childGrid2.selectedRows()).toEqual([]); + HelperUtils.verifyHeaderRowCheckboxState(childGrid1); + HelperUtils.verifyHeaderRowCheckboxState(childGrid2); + + // Select all rows in child + HelperUtils.clickHeaderRowCheckbox(childGrid1); + fix.detectChanges(); + + expect(hierarchicalGrid.selectedRows()).toEqual(['0', '1', '2', '3', '4']); + HelperUtils.verifyHeaderRowCheckboxState(hierarchicalGrid, true); + + expect(childGrid1.selectedRows()).toEqual(['00', '01', '02']); + HelperUtils.verifyHeaderRowCheckboxState(childGrid1, true); + expect(childGrid2.selectedRows()).toEqual([]); + HelperUtils.verifyHeaderRowCheckboxState(childGrid2); + + // Deselect all rows in parent + HelperUtils.clickHeaderRowCheckbox(hierarchicalGrid); + fix.detectChanges(); + + expect(hierarchicalGrid.selectedRows()).toEqual([]); + HelperUtils.verifyHeaderRowCheckboxState(hierarchicalGrid); + + expect(childGrid1.selectedRows()).toEqual(['00', '01', '02']); + HelperUtils.verifyHeaderRowCheckboxState(childGrid1, true); + expect(childGrid2.selectedRows()).toEqual([]); + HelperUtils.verifyHeaderRowCheckboxState(childGrid2); + + // Deselect all rows in child + HelperUtils.clickHeaderRowCheckbox(childGrid1); + fix.detectChanges(); + + expect(hierarchicalGrid.selectedRows()).toEqual([]); + HelperUtils.verifyHeaderRowCheckboxState(hierarchicalGrid); + + expect(childGrid1.selectedRows()).toEqual([]); + HelperUtils.verifyHeaderRowCheckboxState(childGrid1); + expect(childGrid2.selectedRows()).toEqual([]); + HelperUtils.verifyHeaderRowCheckboxState(childGrid2); }); it('should have correct header checkbox state when selecting rows', () => { @@ -150,50 +496,368 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { HelperUtils.verifyHeaderRowCheckboxState(fix, false, true); expect(hierarchicalGrid.selectedRows()).toEqual(['1']); }); + + it('should retain selected row when filtering', () => { + const firstRow = hierarchicalGrid.getRowByIndex(0); + HelperUtils.clickRowCheckbox(firstRow); + fix.detectChanges(); + + hierarchicalGrid.filter('ID', '1', IgxStringFilteringOperand.instance().condition('doesNotContain'), true); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(hierarchicalGrid.getRowByIndex(0)); + HelperUtils.verifyHeaderRowCheckboxState(fix, false, true); + }); + + it('should child grid selection should not be changed when filter parent', () => { + rowIsland1.rowSelection = GridSelectionMode.multiple; + fix.detectChanges(); + + // expand first row + const firstRow = hierarchicalGrid.dataRowList.toArray()[0]; + firstRow.nativeElement.children[0].click(); + fix.detectChanges(); + + // select second row + const secondRow = hierarchicalGrid.dataRowList.toArray()[1]; + HelperUtils.clickRowCheckbox(secondRow); + fix.detectChanges(); + + HelperUtils.verifyHeaderRowCheckboxState(hierarchicalGrid, false, true); + + // Select all rows in child grid + let childGrid = hierarchicalGrid.hgridAPI.getChildGrids(false)[0]; + HelperUtils.clickHeaderRowCheckbox(childGrid); + fix.detectChanges(); + + HelperUtils.verifyHeaderRowCheckboxState(childGrid, true); + + // filter parent grid + hierarchicalGrid.filter('ID', '1', IgxStringFilteringOperand.instance().condition('equals'), true); + fix.detectChanges(); + + HelperUtils.verifyHeaderRowCheckboxState(hierarchicalGrid, true); + + // Expand filtered row + hierarchicalGrid.dataRowList.toArray()[0].nativeElement.children[0].click(); + fix.detectChanges(); + + childGrid = hierarchicalGrid.hgridAPI.getChildGrids(false)[1]; + HelperUtils.verifyHeaderRowCheckboxState(childGrid); + HelperUtils.verifyRowsArraySelected(childGrid.dataRowList.toArray(), false); + + // Clear filter + hierarchicalGrid.clearFilter(); + fix.detectChanges(); + + HelperUtils.verifyHeaderRowCheckboxState(hierarchicalGrid, false, true); + childGrid = hierarchicalGrid.hgridAPI.getChildGrids(false)[0]; + HelperUtils.verifyHeaderRowCheckboxState(childGrid, true); + HelperUtils.verifyRowsArraySelected(childGrid.dataRowList.toArray()); + }); + + it('should not be able to select deleted row', () => { + // Expand first row + const firstRow = hierarchicalGrid.dataRowList.toArray()[0]; + firstRow.nativeElement.children[0].click(); + fix.detectChanges(); + + UIInteractions.simulateClickEvent(firstRow.nativeElement); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(firstRow); + HelperUtils.verifyHeaderRowCheckboxState(fix, false, true); + + // delete selected row + hierarchicalGrid.deleteRow('0'); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(firstRow, false); + HelperUtils.verifyHeaderRowCheckboxState(fix); + expect(hierarchicalGrid.selectedRows()).toEqual([]); + + // Click on deleted row + UIInteractions.simulateClickEvent(firstRow.nativeElement); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(firstRow, false); + HelperUtils.verifyHeaderRowCheckboxState(fix); + expect(hierarchicalGrid.selectedRows()).toEqual([]); + + // Click on checkbox for deleted row + HelperUtils.clickRowCheckbox(firstRow); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(firstRow, false); + HelperUtils.verifyHeaderRowCheckboxState(fix); + expect(hierarchicalGrid.selectedRows()).toEqual([]); + + // Select all rows + hierarchicalGrid.selectAllRows(); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(firstRow, false); + HelperUtils.verifyHeaderRowCheckboxState(fix, true); + expect(hierarchicalGrid.selectedRows()).toEqual(['1', '2', '3', '4']); + + // Click on a row in the child grid + const childGrid = hierarchicalGrid.hgridAPI.getChildGrids(false)[0]; + expect(childGrid.selectedRows()).toEqual([]); + + const childGridFirstRow = childGrid.dataRowList.toArray()[0]; + UIInteractions.simulateClickEvent(childGridFirstRow.nativeElement, false, true); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(firstRow, false); + HelperUtils.verifyHeaderRowCheckboxState(fix, true); + expect(hierarchicalGrid.selectedRows()).toEqual(['1', '2', '3', '4']); + expect(childGrid.selectedRows()).toEqual(['00']); + }); + + it('should be able to select added row', () => { + // Set multiple selection to first row island + rowIsland1.rowSelection = GridSelectionMode.multiple; + fix.detectChanges(); + + // Expand first row + const firstRow = hierarchicalGrid.dataRowList.toArray()[0]; + firstRow.nativeElement.children[0].click(); + fix.detectChanges(); + + HelperUtils.clickHeaderRowCheckbox(hierarchicalGrid); + fix.detectChanges(); + + HelperUtils.verifyHeaderRowCheckboxState(hierarchicalGrid, true); + expect(hierarchicalGrid.selectedRows()).toEqual(['0', '1', '2', '3', '4']); + + hierarchicalGrid.addRow({ ID: '5', ChildLevels: 3, ProductName: 'New Product' }); + fix.detectChanges(); + + HelperUtils.verifyHeaderRowCheckboxState(hierarchicalGrid, false, true); + expect(hierarchicalGrid.selectedRows()).toEqual(['0', '1', '2', '3', '4']); + let lastRow = hierarchicalGrid.dataRowList.toArray()[5]; + HelperUtils.verifyRowSelected(lastRow, false); + + HelperUtils.clickRowCheckbox(lastRow); + fix.detectChanges(); + + HelperUtils.verifyHeaderRowCheckboxState(hierarchicalGrid, true); + expect(hierarchicalGrid.selectedRows()).toEqual(['0', '1', '2', '3', '4', '5']); + + // Add row in child grid + const childGrid = hierarchicalGrid.hgridAPI.getChildGrids(false)[0]; + expect(childGrid.selectedRows()).toEqual([]); + childGrid.addRow({ ID: '03', ChildLevels: 2, ProductName: 'New Product' }); + fix.detectChanges(); + + HelperUtils.clickHeaderRowCheckbox(childGrid); + fix.detectChanges(); + + HelperUtils.verifyHeaderRowCheckboxState(childGrid, true); + expect(childGrid.selectedRows()).toEqual(['00', '01', '02', '03']); + lastRow = childGrid.dataRowList.toArray()[3]; + HelperUtils.verifyRowSelected(lastRow); + }); + }); + + describe('Row Selection CRUD', () => { + beforeEach(fakeAsync(/** height/width setter rAF */() => { + fix = TestBed.createComponent(IgxHierarchicalGridRowSelectionNoTransactionsComponent); + fix.detectChanges(); + hierarchicalGrid = fix.componentInstance.hgrid; + rowIsland1 = fix.componentInstance.rowIsland; + rowIsland2 = fix.componentInstance.rowIsland2; + })); + + it('should deselect deleted row', () => { + HelperUtils.clickHeaderRowCheckbox(hierarchicalGrid); + fix.detectChanges(); + + HelperUtils.verifyHeaderRowCheckboxState(hierarchicalGrid, true); + expect(hierarchicalGrid.selectedRows()).toEqual(['0', '1', '2', '3', '4']); + + hierarchicalGrid.deleteRow('1'); + fix.detectChanges(); + + HelperUtils.verifyHeaderRowCheckboxState(hierarchicalGrid, true); + expect(hierarchicalGrid.selectedRows()).toEqual(['0', '2', '3', '4']); + expect(hierarchicalGrid.dataRowList.length).toEqual(4); + + const firstRow = hierarchicalGrid.dataRowList.toArray()[0]; + HelperUtils.clickRowCheckbox(firstRow); + fix.detectChanges(); + + HelperUtils.verifyHeaderRowCheckboxState(hierarchicalGrid, false, true); + expect(hierarchicalGrid.selectedRows()).toEqual(['2', '3', '4']); + + hierarchicalGrid.deleteRow('0'); + fix.detectChanges(); + + expect(hierarchicalGrid.dataRowList.length).toEqual(3); + HelperUtils.verifyHeaderRowCheckboxState(hierarchicalGrid, true); + expect(hierarchicalGrid.selectedRows()).toEqual(['2', '3', '4']); + }); + + it('should be able to select added row', () => { + const firstRow = hierarchicalGrid.dataRowList.toArray()[0]; + firstRow.nativeElement.children[0].click(); + fix.detectChanges(); + + hierarchicalGrid.addRow({ ID: '5', ChildLevels: 3, ProductName: 'New Product' }); + fix.detectChanges(); + + expect(hierarchicalGrid.dataRowList.length).toEqual(6); + HelperUtils.verifyHeaderRowCheckboxState(hierarchicalGrid); + + hierarchicalGrid.selectAllRows(); + fix.detectChanges(); + + let addedRow = hierarchicalGrid.dataRowList.toArray()[5]; + HelperUtils.verifyHeaderRowCheckboxState(hierarchicalGrid, true); + HelperUtils.verifyRowSelected(addedRow); + + const childGrid = hierarchicalGrid.hgridAPI.getChildGrids(false)[0]; + HelperUtils.clickHeaderRowCheckbox(childGrid); + fix.detectChanges(); + + HelperUtils.verifyHeaderRowCheckboxState(childGrid, true); + + childGrid.addRow({ ID: '03', ChildLevels: 3, ProductName: 'New Product' }); + fix.detectChanges(); + + addedRow = childGrid.dataRowList.toArray()[3]; + HelperUtils.verifyRowSelected(addedRow, false); + HelperUtils.verifyHeaderRowCheckboxState(childGrid, false, true); + HelperUtils.verifyHeaderRowCheckboxState(hierarchicalGrid, true); + + HelperUtils.clickRowCheckbox(addedRow); + fix.detectChanges(); + HelperUtils.verifyRowSelected(addedRow); + HelperUtils.verifyHeaderRowCheckboxState(childGrid, true); + }); }); - describe('Custom row selectors', () => { + describe('Custom selectors', () => { let hGrid; let firstLevelChild; - let secondLevelChild; beforeEach(fakeAsync(() => { fix = TestBed.createComponent(IgxHierarchicalGridCustomSelectorsComponent); fix.detectChanges(); hGrid = fix.componentInstance.hGrid; hGrid.rowSelection = GridSelectionMode.multiple; - firstLevelChild = hGrid.firstLevelChild; - secondLevelChild = hGrid.secondLevelChild; + firstLevelChild = fix.componentInstance.firstLevelChild; })); /** Tests should check root and child grids */ it('Row context `select` method selects a single row', () => { - // TODO + // root grid + const firstRootRow = hGrid.getRowByIndex(0); + firstRootRow.nativeElement.click(); + fix.detectChanges(); + HelperUtils.verifyRowSelected(hGrid.getRowByIndex(0)); + HelperUtils.verifyHeaderRowCheckboxState(fix, false, true); + + // child grid + HelperUtils.expandRowIsland(2); + fix.detectChanges(); + const firstChildRow = firstLevelChild.getRowByIndex(0); + firstChildRow.nativeElement.click(); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(firstLevelChild.getRowByIndex(0)); + HelperUtils.verifyHeaderRowCheckboxState(fix, false, true); }); it('Row context `deselect` method deselects an already selected row', () => { - // TODO + // root grid + const firstRootRow = hGrid.getRowByIndex(1); + HelperUtils.rowCheckboxClick(firstRootRow); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(hGrid.getRowByIndex(1)); + HelperUtils.verifyHeaderRowCheckboxState(fix, false, true); + + HelperUtils.rowCheckboxClick(firstRootRow); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(hGrid.getRowByIndex(1), false); + HelperUtils.verifyHeaderRowCheckboxState(fix, false, false); + + // child grid + HelperUtils.expandRowIsland(2); + const firstLevelChildRow = firstLevelChild.getRowByIndex(0); + HelperUtils.rowCheckboxClick(firstLevelChildRow); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(firstLevelChildRow); + HelperUtils.verifyHeaderRowCheckboxState(fix, false, true); + + HelperUtils.rowCheckboxClick(firstLevelChildRow); + fix.detectChanges(); + + HelperUtils.verifyRowSelected(firstLevelChildRow, false); + HelperUtils.verifyHeaderRowCheckboxState(fix, false, false); }); it('Header context `selectAll` method selects all rows', () => { - // TODO + HelperUtils.clickHeaderRowCheckbox(fix); + fix.detectChanges(); + + HelperUtils.verifyHeaderRowCheckboxState(fix, true, false); + expect(hGrid.selectionService.areAllRowSelected()).toBeTruthy(); }); it('Header context `deselectAll` method deselects all rows', () => { - // TODO - }); + HelperUtils.clickHeaderRowCheckbox(fix); + fix.detectChanges(); - it('Should have the correct properties in the custom row selector template', () => { - // TODO + HelperUtils.verifyHeaderRowCheckboxState(fix, true, false); + expect(hGrid.selectionService.areAllRowSelected()).toBeTruthy(); + + HelperUtils.clickHeaderRowCheckbox(fix); + fix.detectChanges(); + + HelperUtils.verifyHeaderRowCheckboxState(fix, false, false); + expect(hGrid.selectionService.areAllRowSelected()).toBeFalsy(); }); it('Should have the correct properties in the custom row selector header template', () => { - // TODO + spyOn(fix.componentInstance, 'handleHeadSelectorClick').and.callThrough(); + HelperUtils.headerCheckboxClick(fix); + fix.detectChanges(); + + expect(fix.componentInstance.handleHeadSelectorClick).toHaveBeenCalledWith(new MouseEvent('click'), { + selectedCount: 0, + totalCount: hGrid.data.length, + selectAll: jasmine.anything(), + deselectAll: jasmine.anything() + }); + }); + + it('Should have the correct properties in the custom row selector template', () => { + spyOn(fix.componentInstance, 'handleRowSelectorClick').and.callThrough(); + + const firstRootRow = hGrid.getRowByIndex(1); + HelperUtils.rowCheckboxClick(firstRootRow); + fix.detectChanges(); + + expect(fix.componentInstance.handleRowSelectorClick).toHaveBeenCalledWith(new MouseEvent('click'), { + index: 1, + rowID: '1', + selected: false, + select: jasmine.anything(), + deselect: jasmine.anything() + }); }); it('Should have correct indices on all pages', () => { - // TODO + hGrid.nextPage(); + fix.detectChanges(); + + const firstRootRow = hGrid.getRowByIndex(0); + expect(firstRootRow.nativeElement.querySelector('.rowNumber').textContent).toEqual('15'); }); }); }); diff --git a/projects/igniteui-angular/src/lib/grids/igx-selection.module.ts b/projects/igniteui-angular/src/lib/grids/igx-row-selectors.module.ts similarity index 93% rename from projects/igniteui-angular/src/lib/grids/igx-selection.module.ts rename to projects/igniteui-angular/src/lib/grids/igx-row-selectors.module.ts index 157d319ba7f..679650d6a78 100644 --- a/projects/igniteui-angular/src/lib/grids/igx-selection.module.ts +++ b/projects/igniteui-angular/src/lib/grids/igx-row-selectors.module.ts @@ -18,5 +18,5 @@ export class IgxHeadSelectorDirective { declarations: [IgxRowSelectorDirective, IgxHeadSelectorDirective], exports: [IgxRowSelectorDirective, IgxHeadSelectorDirective] }) -export class IgxSelectorsModule { +export class IgxRowSelectorsModule { } diff --git a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-selection.spec.ts b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-selection.spec.ts index 574c73410ff..8a2ed471fe4 100644 --- a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-selection.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-selection.spec.ts @@ -21,7 +21,7 @@ import { import { IgxStringFilteringOperand, IgxNumberFilteringOperand } from '../../data-operations/filtering-condition'; import { configureTestSuite } from '../../test-utils/configure-suite'; import { wait, UIInteractions } from '../../test-utils/ui-interactions.spec'; -import { IgxSelectorsModule } from '../igx-selection.module'; +import { IgxRowSelectorsModule } from '../igx-row-selectors.module'; describe('IgxTreeGrid - Selection #tGrid', () => { configureTestSuite(); @@ -38,7 +38,7 @@ describe('IgxTreeGrid - Selection #tGrid', () => { IgxTreeGridRowEditingTransactionComponent, IgxTreeGridCustomRowSelectorsComponent ], - imports: [IgxTreeGridModule, NoopAnimationsModule, IgxSelectorsModule] + imports: [IgxTreeGridModule, NoopAnimationsModule, IgxRowSelectorsModule] }) .compileComponents(); })); diff --git a/projects/igniteui-angular/src/lib/test-utils/helper-utils.spec.ts b/projects/igniteui-angular/src/lib/test-utils/helper-utils.spec.ts index 5dd5c3d5b93..cf6bd182e4b 100644 --- a/projects/igniteui-angular/src/lib/test-utils/helper-utils.spec.ts +++ b/projects/igniteui-angular/src/lib/test-utils/helper-utils.spec.ts @@ -19,6 +19,8 @@ const HEADER_ROW_CSS_CLASS = '.igx-grid__thead'; const CHECKBOX_INPUT_CSS_CLASS = '.igx-checkbox__input'; const SCROLL_START_CSS_CLASS = '.igx-grid__scroll-start'; const CHECKBOX_ELEMENT = 'igx-checkbox'; +const ICON_CSS_CLASS = 'material-icons igx-icon'; +const CHECKBOX_LBL_CSS_CLASS = '.igx-checkbox__composite'; const DEBOUNCETIME = 50; export function resizeObserverIgnoreError() { @@ -439,17 +441,17 @@ export class HelperUtils { }); } - public static verifyHeaderRowCheckboxState(fix, checked = false, indeterminate = false) { - const header = HelperUtils.getHeaderRow(fix); + public static verifyHeaderRowCheckboxState(parent, checked = false, indeterminate = false) { + const header = HelperUtils.getHeaderRow(parent); const headerCheckboxElement = HelperUtils.getRowCheckboxInput(header); expect(headerCheckboxElement.checked).toBe(checked); expect(headerCheckboxElement.indeterminate).toBe(indeterminate); } - public static verifyHeaderAndRowCheckBoxesAlignment(fix, grid) { - const headerDiv = HelperUtils.getRowCheckboxDiv(HelperUtils.getHeaderRow(fix)); + public static verifyHeaderAndRowCheckBoxesAlignment(grid) { + const headerDiv = HelperUtils.getRowCheckboxDiv(HelperUtils.getHeaderRow(grid)); const firstRowDiv = HelperUtils.getRowCheckboxDiv(grid.rowList.first.nativeElement); - const scrollStartElement = fix.nativeElement.querySelector(SCROLL_START_CSS_CLASS); + const scrollStartElement = grid.nativeElement.querySelector(SCROLL_START_CSS_CLASS); const hScrollbar = grid.parentVirtDir.getHorizontalScroll(); expect(headerDiv.offsetWidth).toEqual(firstRowDiv.offsetWidth); @@ -478,12 +480,12 @@ export class HelperUtils { } } - public static verifyHeaderRowHasCheckbox(fix, hasCheckbox = true, hasCheckboxDiv = true) { - HelperUtils.verifyRowHasCheckbox(HelperUtils.getHeaderRow(fix), hasCheckbox, hasCheckboxDiv, true); + public static verifyHeaderRowHasCheckbox(parent, hasCheckbox = true, hasCheckboxDiv = true) { + HelperUtils.verifyRowHasCheckbox(HelperUtils.getHeaderRow(parent), hasCheckbox, hasCheckboxDiv, true); } - public static getHeaderRow(fix): HTMLElement { - return fix.nativeElement.querySelector(HEADER_ROW_CSS_CLASS); + public static getHeaderRow(parent): HTMLElement { + return parent.nativeElement.querySelector(HEADER_ROW_CSS_CLASS); } public static getRowCheckboxDiv(rowDOM): HTMLElement { @@ -503,8 +505,25 @@ export class HelperUtils { checkboxElement.dispatchEvent(new Event('click', {})); } - public static clickHeaderRowCheckbox(fix) { - const checkboxElement = HelperUtils.getRowCheckboxDiv(HelperUtils.getHeaderRow(fix)); + public static clickHeaderRowCheckbox(parent) { + const checkboxElement = HelperUtils.getRowCheckboxDiv(HelperUtils.getHeaderRow(parent)); checkboxElement.dispatchEvent(new Event('click', {})); } + + // select - deselect a checkbox without a handler + public static rowCheckboxClick(row) { + const checkboxElement = row.nativeElement ? + row.nativeElement.querySelector(CHECKBOX_LBL_CSS_CLASS) : + row.querySelector(CHECKBOX_LBL_CSS_CLASS); + checkboxElement.click(); + } + + public static headerCheckboxClick(fix) { + HelperUtils.rowCheckboxClick(HelperUtils.getHeaderRow(fix)); + } + // + + public static expandRowIsland(rowNumber = 1) { + (document.getElementsByClassName(ICON_CSS_CLASS)[rowNumber]).click(); + } } diff --git a/projects/igniteui-angular/src/lib/test-utils/hierarhical-grid-components.spec.ts b/projects/igniteui-angular/src/lib/test-utils/hierarhical-grid-components.spec.ts index 6a054b0d868..9d9370c51e9 100644 --- a/projects/igniteui-angular/src/lib/test-utils/hierarhical-grid-components.spec.ts +++ b/projects/igniteui-angular/src/lib/test-utils/hierarhical-grid-components.spec.ts @@ -1,11 +1,6 @@ import { Component, ViewChild, OnInit } from '@angular/core'; -import { IgxTreeGridComponent } from '../grids/tree-grid/tree-grid.component'; import { SampleTestData } from './sample-test-data.spec'; -import { IgxNumberSummaryOperand, IgxSummaryResult, IgxColumnComponent } from '../grids'; -import { IgxGridTransaction } from '../grids/grid-base.component'; -import { IgxTransactionService } from '../services/transaction/igx-transaction'; -import { IgxHierarchicalTransactionService } from '../services/transaction/igx-hierarchical-transaction'; -import { DisplayDensity } from '../core/displayDensity'; +import { IgxColumnComponent } from '../grids'; import { IgxHierarchicalTransactionServiceFactory, IgxHierarchicalGridComponent, IgxRowIslandComponent } from 'igniteui-angular'; @Component({ @@ -69,7 +64,7 @@ export class IgxHierarchicalGridTestBaseComponent { - + @@ -92,12 +87,12 @@ export class IgxHierarchicalGridRowSelectionComponent { @Component({ template: ` - - + @@ -106,47 +101,67 @@ export class IgxHierarchicalGridRowSelectionComponent { + + `, +}) +export class IgxHierarchicalGridRowSelectionNoTransactionsComponent { + public data; + @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) public hgrid: IgxHierarchicalGridComponent; + @ViewChild('rowIsland', { read: IgxRowIslandComponent, static: true }) public rowIsland: IgxRowIslandComponent; + @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) public rowIsland2: IgxRowIslandComponent; + + constructor() { + // 3 level hierarchy + this.data = SampleTestData.generateHGridData(5, 3); + } +} + +@Component({ + template: ` + + + + + + - - + - - + {{ rowContext.index }} + + ` }) export class IgxHierarchicalGridCustomSelectorsComponent implements OnInit { public data = []; - @ViewChild('hGgridCustomSelectors', { read: IgxHierarchicalGridComponent, static: true }) + @ViewChild('hGridCustomSelectors', { read: IgxHierarchicalGridComponent, static: true }) public hGrid: IgxHierarchicalGridComponent; @ViewChild('rowIsland1', { read: IgxRowIslandComponent, static: true }) public firstLevelChild: IgxRowIslandComponent; - @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) - public secondLevelChild: IgxRowIslandComponent; - public ngOnInit(): void { - // 3 level hierarchy - this.data = SampleTestData.generateHGridData(40, 3); + // 2 level hierarchy + this.data = SampleTestData.generateHGridData(40, 2); } public handleHeadSelectorClick(event, headContext) { diff --git a/projects/igniteui-angular/src/lib/test-utils/sample-test-data.spec.ts b/projects/igniteui-angular/src/lib/test-utils/sample-test-data.spec.ts index 22f58bf9fc0..58cc633e334 100644 --- a/projects/igniteui-angular/src/lib/test-utils/sample-test-data.spec.ts +++ b/projects/igniteui-angular/src/lib/test-utils/sample-test-data.spec.ts @@ -1566,7 +1566,7 @@ export class SampleTestData { for (let i = 0; i < count; i++) { const rowID = parendID ? parendID + i : i.toString(); if (level > 0 ) { - children = this.generateData(count / 2 , currLevel - 1, rowID); + children = this.generateHGridData(count / 2 , currLevel - 1, rowID); } prods.push({ ID: rowID, ChildLevels: currLevel, ProductName: 'Product: A' + i, 'Col1': i,