Skip to content

feat(h-grid): update adv filtering schema on row expand #15927

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

All notable changes for each version of this project will be documented in this file.

## 20.1.0

### General
- `IgxHierarchicalGrid`
- **Deprecation** - `schema` input property has been deprecated and will be removed in a future version.

## 20.0.2

### New Features
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { QueryBuilderFunctions } from '../../query-builder/query-builder-functio
import { By } from '@angular/platform-browser';
import { IgxDateTimeEditorDirective } from '../../directives/date-time-editor/date-time-editor.directive';
import { QueryBuilderSelectors } from '../../query-builder/query-builder.common';
import { IgxHGridRemoteOnDemandComponent } from '../hierarchical-grid/hierarchical-grid.spec';
import { IgxHGridRemoteOnDemandComponent, IgxHierarchicalGridToggleRIComponent } from '../hierarchical-grid/hierarchical-grid.spec';
import { IGridResourceStrings } from '../../core/i18n/grid-resources';

describe('IgxGrid - Advanced Filtering #grid - ', () => {
Expand Down Expand Up @@ -1750,76 +1750,69 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => {
expect(hgrid.filteredData.length).toBe(5);
}));

it('Should have proper fields in UI when schema is defined with load on demand.', fakeAsync(() => {
const fixture = TestBed.createComponent(IgxHGridRemoteOnDemandComponent);
const hierarchicalGrid = fixture.componentInstance.instance;
it('Should update root grid schema when row island is expanded.', fakeAsync(() => {
const fixture = TestBed.createComponent(IgxHierarchicalGridToggleRIComponent);
const hierarchicalGrid = fixture.componentInstance.hgrid;
hierarchicalGrid.allowAdvancedFiltering = true;
hierarchicalGrid.schema = [
{
name: 'rootLevel',
fields: [
{ field: 'ID', dataType: 'string' },
{ field: 'ChildLevels', dataType: 'number' },
{ field: 'ProductName', dataType: 'string' },
{ field: 'Col1', dataType: 'number' },
{ field: 'Col2', dataType: 'number' },
{ field: 'Col3', dataType: 'number' }
],
childEntities: [
{
name: 'childData',
fields: [
{ field: 'ID', dataType: 'string' },
{ field: 'ProductName', dataType: 'string' }
],
childEntities: [
{
name: 'childData2',
fields: [
{ field: 'ID', dataType: 'string' },
{ field: 'ProductName', dataType: 'string' }
]
}
]
}
]
}
]
fixture.detectChanges();

hierarchicalGrid.openAdvancedFilteringDialog();
fixture.detectChanges();

// Click the initial 'Add Condition' button.
QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fixture, 0);
tick(100);
fixture.detectChanges();
// Populate edit inputs.
QueryBuilderFunctions.selectColumnInEditModeExpression(fixture, 0); // Select 'ID' column.
QueryBuilderFunctions.selectOperatorInEditModeExpression(fixture, 10); // Select 'In' operator.
tick(100);
fixture.detectChanges();

const entityInputGroup = QueryBuilderFunctions.getQueryBuilderEntitySelect(fixture, 1).querySelector('input');
expect(entityInputGroup.value).toBe('childData');
// Open advanced filtering dialog and create an 'In' condition.
const createInConditionAndGetReturnFields = () => {
// Open Advanced Filtering dialog.
hierarchicalGrid.openAdvancedFilteringDialog();
fixture.detectChanges();

// Click the initial 'Add Condition' button.
QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fixture, 0);
tick(100);
fixture.detectChanges();
// Populate edit inputs.
QueryBuilderFunctions.selectColumnInEditModeExpression(fixture, 0); // Select 'ID' column.
QueryBuilderFunctions.selectOperatorInEditModeExpression(fixture, 10); // Select 'In' operator.
tick(100);
fixture.detectChanges();

// Verify entities
QueryBuilderFunctions.clickQueryBuilderEntitySelect(fixture, 1);
fixture.detectChanges();
const queryBuilderElement: HTMLElement = fixture.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}`))[1].nativeElement;
let dropdownValues: string[] = QueryBuilderFunctions.getQueryBuilderSelectDropdownItems(queryBuilderElement).map((x: any) => x.innerText);
let expectedValues = ['childData'];
expect(dropdownValues).toEqual(expectedValues);

// Verify return fields
QueryBuilderFunctions.clickQueryBuilderFieldsCombo(fixture, 1);
fixture.detectChanges();
const innerQueryReturnFields = QueryBuilderFunctions.getQueryBuilderSelectDropdown(queryBuilderElement, 1);

return innerQueryReturnFields;
};

const fieldInputGroup = QueryBuilderFunctions.getQueryBuilderFieldsCombo(fixture, 1).querySelector('input');
expect(fieldInputGroup.value).toBe('ID');
let innerQueryReturnFields = createInConditionAndGetReturnFields();
expect(innerQueryReturnFields).toBeNull();

// Verify entities
QueryBuilderFunctions.clickQueryBuilderEntitySelect(fixture, 1);
// Close Advanced Filtering dialog.
hierarchicalGrid.closeAdvancedFilteringDialog(false);
tick(200);
fixture.detectChanges();
const queryBuilderElement: HTMLElement = fixture.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}`))[1].nativeElement;
let dropdownValues: string[] = QueryBuilderFunctions.getQueryBuilderSelectDropdownItems(queryBuilderElement).map((x: any) => x.innerText);
let expectedValues = ['childData'];
expect(dropdownValues).toEqual(expectedValues);

// Verify return fileds
QueryBuilderFunctions.clickQueryBuilderFieldsCombo(fixture, 1);
// Expand row island
const row = hierarchicalGrid.gridAPI.get_row_by_index(0) as any;
UIInteractions.simulateClickAndSelectEvent(row.expander);
fixture.detectChanges();
dropdownValues = QueryBuilderFunctions.getQueryBuilderSelectDropdownItems(queryBuilderElement, 1).map((x: any) => x.innerText);
expectedValues = ['ID', 'ProductName'];
expect(dropdownValues).toEqual(expectedValues);

// Open advanced filtering dialog and verify that schema is updated.
innerQueryReturnFields = createInConditionAndGetReturnFields();
expect(innerQueryReturnFields).not.toBeNull();
const items = Array.from(innerQueryReturnFields.querySelectorAll('.igx-drop-down__item'));
expect(items.length).toBe(7);
expect((items[0] as HTMLElement).innerText).toBe('ID');
expect((items[1] as HTMLElement).innerText).toBe('ChildLevels');
expect((items[2] as HTMLElement).innerText).toBe('ProductName');
expect((items[3] as HTMLElement).innerText).toBe('Col1');
expect((items[4] as HTMLElement).innerText).toBe('Col2');
expect((items[5] as HTMLElement).innerText).toBe('Col3');
expect((items[6] as HTMLElement).innerText).toBe('childData2');
}));

it('Should correctly change resource strings for hierarchical Advanced Filtering dialog.', fakeAsync(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -587,11 +587,10 @@ export class IgxHierarchicalGridComponent extends IgxHierarchicalGridBaseDirecti
* const schema = this.grid.schema;
* this.grid.schema = [{ name: 'Products', fields: [...], childEntities: [...] }];
* ```
* @deprecated in version 20.1.0.
*/
@Input()
public set schema(entities: EntityType[]) {
this._hGridSchema = entities;
}
public set schema(entities: EntityType[]) {}

/* blazorSuppress */
public get schema() {
Expand Down Expand Up @@ -683,6 +682,10 @@ export class IgxHierarchicalGridComponent extends IgxHierarchicalGridBaseDirecti
this.batchEditing = val;
});
}
this.columnsAutogenerated.subscribe((e) => {
this.updateRootGridSchema(e);
});

super.ngOnInit();
}

Expand Down Expand Up @@ -1234,7 +1237,7 @@ export class IgxHierarchicalGridComponent extends IgxHierarchicalGridBaseDirecti
}

private generateSchema() {
const filterableFields = this.columns.filter((column) => !column.columnGroup && column.filterable);
const filterableFields: FieldType[] = this.columns.filter((column) => !column.columnGroup && column.filterable);
let entities: EntityType[];

if(filterableFields.length !== 0) {
Expand All @@ -1244,8 +1247,8 @@ export class IgxHierarchicalGridComponent extends IgxHierarchicalGridBaseDirecti
fields: filterableFields.map(f => ({
field: f.field,
dataType: f.dataType,
// label: f.label,
// header: f.header,
label: f.label,
header: f.header,
editorOptions: f.editorOptions,
filters: f.filters,
pipeArgs: f.pipeArgs,
Expand All @@ -1256,40 +1259,62 @@ export class IgxHierarchicalGridComponent extends IgxHierarchicalGridBaseDirecti
];

entities[0].childEntities = this.childLayoutList.reduce((acc, rowIsland) => {
return acc.concat(this.generateChildEntity(rowIsland, this.data[0][rowIsland.key][0]));
return acc.concat(this.generateChildEntity(rowIsland));
}
, []);
}

return entities;
}

private generateChildEntity(rowIsland: IgxRowIslandComponent, firstRowData: any[]): EntityType {
private updateRootGridSchema(event: any) {
const schema = (this.rootGrid as IgxHierarchicalGridComponent).schema;
if (!schema || schema.length === 0) {
return;
}

let path = [];
let parentIsland = this.parentIsland;
while (parentIsland) {
path.push(parentIsland.key);
parentIsland = parentIsland.parentIsland;
}

path.reverse();
if (path.length > 0) {
let childEntity = schema[0];
for (let i = 0; i < path.length; i++) {
childEntity = childEntity.childEntities.find(e => e.name === path[i]);
}

if (childEntity) {
childEntity.fields = event.columns.filter((column) => !column.columnGroup && column.filterable)
.map(f => ({
field: f.field,
dataType: f.dataType,
label: f.label,
header: f.header,
editorOptions: f.editorOptions,
filters: f.filters,
pipeArgs: f.pipeArgs,
defaultTimeFormat: f.defaultTimeFormat,
defaultDateTimeFormat: f.defaultDateTimeFormat
})) as FieldType[];
}
}
}

private generateChildEntity(rowIsland: IgxRowIslandComponent): EntityType {
const entityName = rowIsland.key;
let fields = [];
let childEntities;
if (!rowIsland.autoGenerate) {
if (rowIsland.childColumns?.length > 0) {
fields = flatten(rowIsland.childColumns.toArray()).filter(col => col.field)
.map(f => ({ field: f.field, dataType: f.dataType })) as FieldType[];
} else if (firstRowData) {
const rowIslandFields = Object.keys(firstRowData).map(key => {
if (firstRowData[key] instanceof Array) {
return null;
}

return {
field: key,
dataType: this.resolveDataTypes(firstRowData[key])
}
});
fields = rowIslandFields.filter(f => f !== null) as FieldType[];
}

const rowIslandChildEntities = rowIsland.childLayoutList.reduce((acc, childRowIsland) => {
if (!firstRowData) {
return null;
}
return acc.concat(this.generateChildEntity(childRowIsland, firstRowData[childRowIsland.key][0]));
return acc.concat(this.generateChildEntity(childRowIsland));
}, []);

if (rowIslandChildEntities?.length > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1410,7 +1410,7 @@ export class IgxQueryBuilderTreeComponent implements AfterViewInit, OnDestroy {
* @hidden @internal
*/
public getFormat(field: string) {
return this.fields?.find(el => el.field === field).pipeArgs.format;
return this.fields?.find(el => el.field === field)?.pipeArgs.format;
}

/**
Expand Down
Loading