Skip to content
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

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

## 20.2.0

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

## 20.1.0

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, IgxHierarchicalGridMissingChildDataComponent } from '../hierarchical-grid/hierarchical-grid.spec';
import { IgxHGridRemoteOnDemandComponent, IgxHierarchicalGridMissingChildDataComponent, 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();
// 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();
// 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');
// 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);

const fieldInputGroup = QueryBuilderFunctions.getQueryBuilderFieldsCombo(fixture, 1).querySelector('input');
expect(fieldInputGroup.value).toBe('ID');
// Verify return fields
QueryBuilderFunctions.clickQueryBuilderFieldsCombo(fixture, 1);
fixture.detectChanges();
const innerQueryReturnFields = QueryBuilderFunctions.getQueryBuilderSelectDropdown(queryBuilderElement, 1);

return innerQueryReturnFields;
};

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 @@ -590,11 +590,10 @@ export class IgxHierarchicalGridComponent extends IgxHierarchicalGridBaseDirecti
* const schema = this.grid.schema;
* this.grid.schema = [{ name: 'Products', fields: [...], childEntities: [...] }];
* ```
* @deprecated in version 20.2.0.
*/
@Input()
public set schema(entities: EntityType[]) {
this._hGridSchema = entities;
}
public set schema(entities: EntityType[]) {}

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

super.ngOnInit();
}

Expand Down Expand Up @@ -1238,7 +1241,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 @@ -1248,6 +1251,7 @@ export class IgxHierarchicalGridComponent extends IgxHierarchicalGridBaseDirecti
fields: filterableFields.map(f => ({
field: f.field,
dataType: f.dataType,
label: f.label,
header: f.header,
editorOptions: f.editorOptions,
filters: f.filters,
Expand All @@ -1259,44 +1263,62 @@ export class IgxHierarchicalGridComponent extends IgxHierarchicalGridBaseDirecti
];

entities[0].childEntities = this.childLayoutList.reduce((acc, rowIsland) => {
const childFirstRowData = this.data?.length > 0 && this.data[0][rowIsland.key]?.length > 0 ?
this.data[0][rowIsland.key][0] : null;
return acc.concat(this.generateChildEntity(rowIsland, childFirstRowData));
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;
}
const childFirstRowData = firstRowData.length > 0 && firstRowData[childRowIsland.key]?.length > 0 ?
firstRowData[childRowIsland.key][0] : null;
return acc.concat(this.generateChildEntity(childRowIsland, childFirstRowData));
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