Skip to content

Commit c99e523

Browse files
authored
Merge branch '18.1.x' into mkirkova/fix-14086-18.1.x
2 parents 6eb7008 + 56b32d2 commit c99e523

File tree

12 files changed

+212
-42
lines changed

12 files changed

+212
-42
lines changed

projects/igniteui-angular-elements/src/app/app.module.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,5 +123,6 @@ declare global {
123123
'igc-grid': NgElement & WithProperties<GridType>;
124124
'igc-tree-grid': NgElement & WithProperties<IgxTreeGridElement>;
125125
'igc-paginator': NgElement & WithProperties<IgxPaginatorComponent>;
126+
'igc-grid-state': NgElement & WithProperties<IgxGridStateComponent>;
126127
}
127128
}

projects/igniteui-angular-elements/src/app/custom-strategy.spec.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ import { ApplicationRef, importProvidersFrom } from '@angular/core';
33
import { createApplication } from '@angular/platform-browser';
44
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
55
import { BrowserTestingModule } from '@angular/platform-browser/testing';
6-
import { IgxColumnComponent, IgxGridComponent, IgxHierarchicalGridComponent, IgxPaginatorComponent } from 'igniteui-angular';
6+
import { IgxColumnComponent, IgxGridComponent, IgxHierarchicalGridComponent, IgxPaginatorComponent, IgxPivotGridComponent } from 'igniteui-angular';
77
import { firstValueFrom, fromEvent, skip, timer } from 'rxjs';
88
import { registerConfig } from '../analyzer/elements.config';
99
import { createIgxCustomElement } from './create-custom-element';
1010
import { ComponentRefKey, IgcNgElement } from './custom-strategy';
1111
import hgridData from '../assets/data/projects-hgrid.js';
1212
import { SampleTestData } from 'igniteui-angular/src/lib/test-utils/sample-test-data.spec';
1313
import { ELEMENTS_TOKEN } from 'igniteui-angular/src/lib/core/utils';
14+
import { IgxGridStateComponent } from '../lib/state.component';
1415

1516
describe('Elements: ', () => {
1617
let testContainer: HTMLDivElement;
@@ -28,8 +29,13 @@ describe('Elements: ', () => {
2829
customElements.define("igc-grid", grid);
2930
const hgrid = createIgxCustomElement<IgxHierarchicalGridComponent>(IgxHierarchicalGridComponent, { injector: appRef.injector, registerConfig });
3031
customElements.define("igc-hierarchical-grid", hgrid);
32+
const pivotGrid = createIgxCustomElement<IgxPivotGridComponent>(IgxPivotGridComponent, { injector: appRef.injector, registerConfig });
33+
customElements.define("igc-pivot-grid", pivotGrid);
3134
const paginator = createIgxCustomElement<IgxPaginatorComponent>(IgxPaginatorComponent, { injector: appRef.injector, registerConfig });
3235
customElements.define("igc-paginator", paginator);
36+
const stateComponent = createIgxCustomElement<IgxGridStateComponent>(IgxGridStateComponent, { injector: appRef.injector, registerConfig });
37+
customElements.define("igc-grid-state", stateComponent);
38+
3339
});
3440

3541
beforeEach(async () => {
@@ -111,5 +117,19 @@ describe('Elements: ', () => {
111117
expect(gridEl.dataView.length).toEqual(3);
112118
expect(paginator.totalRecords).toEqual(gridEl.data.length);
113119
});
120+
121+
it(`should initialize pivot grid with state persistence component`, async () => {
122+
const gridEl = document.createElement("igc-pivot-grid");
123+
124+
const stateComponent = document.createElement("igc-grid-state");
125+
126+
gridEl.appendChild(stateComponent);
127+
128+
testContainer.appendChild(gridEl);
129+
130+
// TODO: Better way to wait - potentially expose the queue or observable for update on the strategy
131+
await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 2));
132+
expect(() => stateComponent.getStateAsString()).not.toThrow();
133+
});
114134
});
115135
});

projects/igniteui-angular-elements/src/lib/state.component.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Component, EnvironmentInjector, EventEmitter, Inject, Injector, Output, ViewContainerRef } from '@angular/core';
2-
import { IGX_GRID_SERVICE_BASE, GridServiceType, IPinningConfig} from '../../../igniteui-angular/src/lib/grids/common/grid.interface';
2+
import { IPinningConfig, GridType, IGX_GRID_BASE} from '../../../igniteui-angular/src/lib/grids/common/grid.interface';
33
import { IFilteringExpressionsTree } from '../../../igniteui-angular/src/lib/data-operations/filtering-expressions-tree';
44
import { IPagingState } from '../../../igniteui-angular/src/lib/data-operations/paging-state.interface';
55
import { ISortingExpression } from '../../../igniteui-angular/src/lib/data-operations/sorting-strategy';
@@ -50,11 +50,11 @@ export interface IGridStateInfo {
5050
export class IgxGridStateComponent extends IgxGridStateBaseDirective {
5151

5252
constructor(
53-
@Inject(IGX_GRID_SERVICE_BASE) private api: GridServiceType,
53+
@Inject(IGX_GRID_BASE) grid: GridType,
5454
protected override viewRef: ViewContainerRef, protected override envInjector: EnvironmentInjector,
5555
protected override injector: Injector,
5656
) {
57-
super(api.grid, viewRef, envInjector, injector);
57+
super(grid, viewRef, envInjector, injector);
5858
}
5959

6060
/**

projects/igniteui-angular/src/lib/core/styles/components/navdrawer/_navdrawer-theme.scss

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,13 +384,18 @@
384384
}
385385

386386
@if $variant == 'material' {
387+
$reduce-size: rem(8px);
388+
389+
// The clip path here fixes a bug: https://github.com/IgniteUI/igniteui-angular/issues/14554
390+
clip-path: inset(calc($reduce-size / 2) 0 round var-get($theme, 'item-border-radius'));
391+
387392
&::after {
388393
content: '';
389394
position: absolute;
390395
width: 100%;
391396
inset-block-start: rem(4px);
392397
inset-inline-start: 0;
393-
height: calc(100% - #{rem(8px)});
398+
height: calc(100% - #{$reduce-size});
394399
border-radius: var-get($theme, 'item-border-radius');
395400
z-index: -1;
396401
}

projects/igniteui-angular/src/lib/directives/divider/divider.directive.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ export class IgxDividerDirective {
8383
* ```
8484
*/
8585
@HostBinding('style.--inset')
86+
@Input()
8687
public set inset(value: string) {
8788
this._inset = value;
8889
}
@@ -105,7 +106,6 @@ export class IgxDividerDirective {
105106
* <igx-divider inset="16px"></igx-divider>
106107
* ```
107108
*/
108-
@Input('inset')
109109
private _inset = '0';
110110

111111
/**

projects/igniteui-angular/src/lib/drop-down/drop-down.base.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ export abstract class IgxDropDownBaseDirective implements IDropDownList, OnInit
7474
* <igx-drop-down [id]='newDropDownId'></igx-drop-down>
7575
* ```
7676
*/
77+
@HostBinding('attr.id')
7778
@Input()
7879
public get id(): string {
7980
return this._id;

projects/igniteui-angular/src/lib/grids/grid-base.directive.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1131,7 +1131,7 @@ export abstract class IgxGridBaseDirective implements GridType,
11311131
@ViewChild('igxLoadingOverlayOutlet', { read: IgxOverlayOutletDirective, static: true })
11321132
public loadingOutlet: IgxOverlayOutletDirective;
11331133

1134-
/* contentChildren */
1134+
/* reactContentChildren */
11351135
/* blazorInclude */
11361136
/* blazorTreatAsCollection */
11371137
/* blazorCollectionName: ColumnCollection */

projects/igniteui-angular/src/lib/grids/grid/grid-filtering-advanced.spec.ts

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ import {
1515
IgxGridAdvancedFilteringComponent,
1616
IgxGridExternalAdvancedFilteringComponent,
1717
IgxGridAdvancedFilteringBindingComponent,
18-
IgxGridAdvancedFilteringOverlaySettingsComponent
18+
IgxGridAdvancedFilteringOverlaySettingsComponent,
19+
IgxGridAdvancedFilteringDynamicColumnsComponent
1920
} from '../../test-utils/grid-samples.spec';
2021
import { ControlsFunction } from '../../test-utils/controls-functions.spec';
2122
import { FormattedValuesFilteringStrategy } from '../../data-operations/filtering-strategy';
2223
import { IgxHierGridExternalAdvancedFilteringComponent } from '../../test-utils/hierarchical-grid-components.spec';
2324
import { IgxHierarchicalGridComponent } from '../hierarchical-grid/public_api';
2425
import { IFilteringEventArgs } from '../public_api';
26+
import { SampleTestData } from '../../test-utils/sample-test-data.spec';
2527

2628
const ADVANCED_FILTERING_OPERATOR_LINE_AND_CSS_CLASS = 'igx-filter-tree__line--and';
2729
const ADVANCED_FILTERING_OPERATOR_LINE_OR_CSS_CLASS = 'igx-filter-tree__line--or';
@@ -38,7 +40,8 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => {
3840
IgxGridAdvancedFilteringComponent,
3941
IgxGridExternalAdvancedFilteringComponent,
4042
IgxGridAdvancedFilteringBindingComponent,
41-
IgxHierGridExternalAdvancedFilteringComponent
43+
IgxHierGridExternalAdvancedFilteringComponent,
44+
IgxGridAdvancedFilteringDynamicColumnsComponent
4245
]
4346
});
4447
}));
@@ -2048,6 +2051,78 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => {
20482051
expect(rows.length).toEqual(1, 'Wrong filtered rows count');
20492052
}));
20502053

2054+
it('should handle advanced filtering correctly when grid columns and data are dynamically changed', fakeAsync(() => {
2055+
const fixture = TestBed.createComponent(IgxGridAdvancedFilteringDynamicColumnsComponent);
2056+
grid = fixture.componentInstance.grid;
2057+
fixture.detectChanges();
2058+
2059+
expect(grid.filteredData).toBeNull();
2060+
expect(grid.rowList.length).toBe(8);
2061+
expect(GridFunctions.getCurrentCellFromGrid(grid, 0, 1).value).toBe('Ignite UI for JavaScript');
2062+
expect(GridFunctions.getCurrentCellFromGrid(grid, 1, 1).value).toBe('NetAdvantage');
2063+
2064+
// Open Advanced Filtering dialog
2065+
GridFunctions.clickAdvancedFilteringButton(fixture);
2066+
fixture.detectChanges();
2067+
2068+
// Click the initial 'Add And Group' button
2069+
GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fixture, 0);
2070+
tick(100);
2071+
fixture.detectChanges();
2072+
2073+
// Populate edit inputs
2074+
selectColumnInEditModeExpression(fixture, 1);
2075+
selectOperatorInEditModeExpression(fixture, 2);
2076+
const input = GridFunctions.getAdvancedFilteringValueInput(fixture).querySelector('input');
2077+
UIInteractions.clickAndSendInputElementValue(input, 'ign', fixture);
2078+
2079+
// Commit the populated expression
2080+
GridFunctions.clickAdvancedFilteringExpressionCommitButton(fixture);
2081+
fixture.detectChanges();
2082+
2083+
// Apply the filters
2084+
GridFunctions.clickAdvancedFilteringApplyButton(fixture);
2085+
fixture.detectChanges();
2086+
2087+
// Verify the filter results
2088+
expect(grid.filteredData.length).toEqual(2);
2089+
expect(grid.rowList.length).toBe(2);
2090+
expect(GridFunctions.getCurrentCellFromGrid(grid, 0, 1).value).toBe('Ignite UI for JavaScript');
2091+
expect(GridFunctions.getCurrentCellFromGrid(grid, 1, 1).value).toBe('Ignite UI for Angular');
2092+
2093+
// Change the grid's columns collection
2094+
fixture.componentInstance.columns = [
2095+
{ field: 'ID', header: 'ID', width: '200px', type: 'string' },
2096+
{ field: 'CompanyName', header: 'Company Name', width: '200px', type: 'string'},
2097+
{ field: 'ContactName', header: 'Contact Name', width: '200px', type: 'string' },
2098+
{ field: 'ContactTitle', header: 'Contact Title', width: '200px', type: 'string' },
2099+
{ field: 'City', header: 'City', width: '200px', type: 'string' },
2100+
{ field: 'Country', header: 'Country', width: '200px', type: 'string' },
2101+
];
2102+
fixture.detectChanges();
2103+
flush();
2104+
2105+
// Change the grid's data collection
2106+
grid.data = SampleTestData.contactInfoDataFull();
2107+
fixture.detectChanges();
2108+
flush();
2109+
2110+
// Spy for error messages in the console
2111+
const consoleSpy = spyOn(console, 'error');
2112+
2113+
// Open Advanced Filtering dialog
2114+
GridFunctions.clickAdvancedFilteringButton(fixture);
2115+
fixture.detectChanges();
2116+
flush();
2117+
2118+
// Verify the filters are cleared
2119+
expect(grid.filteredData).toEqual([]);
2120+
expect(grid.rowList.length).toBe(0);
2121+
2122+
// Check for error messages in the console
2123+
expect(consoleSpy).not.toHaveBeenCalled();
2124+
}));
2125+
20512126
describe('Context Menu - ', () => {
20522127
it('Should discard added group when clicking its operator line without having a single expression.', fakeAsync(() => {
20532128
// Open Advanced Filtering dialog.

projects/igniteui-angular/src/lib/query-builder/query-builder.component.ts

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -988,31 +988,33 @@ export class IgxQueryBuilderComponent implements AfterViewInit, OnDestroy {
988988
this.currentGroup = groupItem;
989989
}
990990

991-
private createExpressionGroupItem(expressionTree: IExpressionTree, parent?: ExpressionGroupItem): ExpressionGroupItem {
992-
let groupItem: ExpressionGroupItem;
993-
if (expressionTree) {
994-
groupItem = new ExpressionGroupItem(expressionTree.operator, parent);
995-
996-
for (const expr of expressionTree.filteringOperands) {
997-
if (expr instanceof FilteringExpressionsTree) {
998-
groupItem.children.push(this.createExpressionGroupItem(expr, groupItem));
999-
} else {
1000-
const filteringExpr = expr as IFilteringExpression;
1001-
const exprCopy: IFilteringExpression = {
1002-
fieldName: filteringExpr.fieldName,
1003-
condition: filteringExpr.condition,
1004-
searchVal: filteringExpr.searchVal,
1005-
ignoreCase: filteringExpr.ignoreCase
1006-
};
991+
private createExpressionGroupItem(expressionTree: IExpressionTree, parent?: ExpressionGroupItem): ExpressionGroupItem | null {
992+
if (!expressionTree) {
993+
return null;
994+
}
995+
996+
const groupItem = new ExpressionGroupItem(expressionTree.operator, parent);
997+
998+
for (const expr of expressionTree.filteringOperands) {
999+
if (expr instanceof FilteringExpressionsTree) {
1000+
const childGroup = this.createExpressionGroupItem(expr, groupItem);
1001+
if (childGroup) {
1002+
groupItem.children.push(childGroup);
1003+
}
1004+
} else {
1005+
const filteringExpr = expr as IFilteringExpression;
1006+
const field = this.fields.find(el => el.field === filteringExpr.fieldName);
1007+
1008+
if (field) {
1009+
const exprCopy: IFilteringExpression = { ...filteringExpr };
10071010
const operandItem = new ExpressionOperandItem(exprCopy, groupItem);
1008-
const field = this.fields.find(el => el.field === filteringExpr.fieldName);
10091011
operandItem.fieldLabel = field.label || field.header || field.field;
10101012
groupItem.children.push(operandItem);
10111013
}
10121014
}
10131015
}
10141016

1015-
return groupItem;
1017+
return groupItem.children.length > 0 ? groupItem : null;
10161018
}
10171019

10181020
private createExpressionTreeFromGroupItem(groupItem: ExpressionGroupItem): FilteringExpressionsTree {

projects/igniteui-angular/src/lib/select/select.component.spec.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ describe('igxSelect', () => {
9898
IgxSelectReactiveFormComponent,
9999
IgxSelectTemplateFormComponent,
100100
IgxSelectHeaderFooterComponent,
101-
IgxSelectCDRComponent
101+
IgxSelectCDRComponent,
102+
IgxSelectWithIdComponent
102103
]
103104
}).compileComponents();
104105
}));
@@ -515,6 +516,21 @@ describe('igxSelect', () => {
515516
expect(dummyInput).toEqual(document.activeElement);
516517
expect(select.collapsed).toBeFalsy();
517518
}));
519+
520+
it('should set the id attribute when using property binding', () => {
521+
fixture = TestBed.createComponent(IgxSelectWithIdComponent);
522+
fixture.detectChanges();
523+
524+
select = fixture.componentInstance.select;
525+
fixture.detectChanges();
526+
527+
const selectElement = fixture.debugElement.query(By.css('igx-select')).nativeElement;
528+
fixture.detectChanges();
529+
530+
expect(select).toBeTruthy();
531+
expect(select.id).toEqual("id1");
532+
expect(selectElement.getAttribute('id')).toBe('id1');
533+
});
518534
});
519535

520536
describe('Form tests: ', () => {
@@ -3091,3 +3107,21 @@ class IgxSelectCDRComponent {
30913107
{ field: 'ContactName', type: 'string' }
30923108
];
30933109
}
3110+
3111+
@Component({
3112+
template: `
3113+
<igx-select [id]="'id1'">
3114+
<igx-select-item *ngFor="let item of items" [value]="item">
3115+
{{item}}
3116+
</igx-select-item>
3117+
</igx-select>
3118+
`,
3119+
standalone: true,
3120+
imports: [NgIf, IgxSelectComponent, IgxSelectItemComponent, IgxLabelDirective, NgFor]
3121+
})
3122+
class IgxSelectWithIdComponent {
3123+
@ViewChild(IgxSelectComponent, { read: IgxSelectComponent, static: true })
3124+
public select: IgxSelectComponent;
3125+
3126+
public items: string[] = ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5'];
3127+
}

0 commit comments

Comments
 (0)