Skip to content

Commit aea4b3b

Browse files
authored
Merge branch '8.2.x' into mvenkov/fix-overlay-position-8.2.x
2 parents d6efe5f + cedc291 commit aea4b3b

16 files changed

+195
-42
lines changed

projects/igniteui-angular/src/lib/directives/template-outlet/template_outlet.directive.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ export class IgxTemplateOutletDirective implements OnChanges {
106106
this._viewContainerRef.insert(view, 0);
107107
this._updateExistingContext(this.igxTemplateOutletContext);
108108
this.onViewMoved.emit({ owner: this, view: this._viewRef, context: this.igxTemplateOutletContext });
109+
} else {
110+
this._updateExistingContext(this.igxTemplateOutletContext);
109111
}
110112
}
111113
private _useCachedView() {

projects/igniteui-angular/src/lib/grids/filtering/advanced-filtering/advanced-filtering-dialog.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ <h6 class="igx-filter-empty__title">
9696
(onRemove)="onChipRemove(expressionItem)"
9797
(onSelectionDone)="onChipSelectionEnd()"
9898
>
99-
<span igxPrefix class="igx-filter-tree__expression-column">{{ expressionItem.expression.fieldName }}</span>
99+
<span igxPrefix class="igx-filter-tree__expression-column">{{ expressionItem.columnHeader || expressionItem.expression.fieldName }}</span>
100100
<igx-icon
101101
igxPrefix
102102
fontSet="filtering-icons"

projects/igniteui-angular/src/lib/grids/filtering/advanced-filtering/advanced-filtering-dialog.component.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class ExpressionOperandItem extends ExpressionItem {
5656
inEditMode: boolean;
5757
inAddMode: boolean;
5858
hovered: boolean;
59+
columnHeader: string;
5960
}
6061

6162
/**
@@ -303,6 +304,7 @@ export class IgxAdvancedFilteringDialogComponent implements AfterViewInit, OnDes
303304
this.editedExpression.expression.fieldName = this.selectedColumn.field;
304305
this.editedExpression.expression.condition = this.selectedColumn.filters.condition(this.selectedCondition);
305306
this.editedExpression.expression.searchVal = DataUtil.parseValue(this.selectedColumn.dataType, this.searchValue);
307+
this.editedExpression.columnHeader = this.selectedColumn.header;
306308

307309
this.editedExpression.inEditMode = false;
308310
this.editedExpression = null;
@@ -386,6 +388,8 @@ export class IgxAdvancedFilteringDialogComponent implements AfterViewInit, OnDes
386388
ignoreCase: filteringExpr.ignoreCase
387389
};
388390
const operandItem = new ExpressionOperandItem(exprCopy, groupItem);
391+
const column = this.grid.getColumnByName(filteringExpr.fieldName);
392+
operandItem.columnHeader = column.header;
389393
groupItem.children.push(operandItem);
390394
}
391395
}

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,6 +1556,24 @@ export abstract class IgxGridBaseComponent extends DisplayDensityBase implements
15561556
@Output()
15571557
public onRowDeleted = new EventEmitter<IRowDataEventArgs>();
15581558

1559+
/**
1560+
* Returns the state of the grid virtualization, including the start index and how many records are rendered.
1561+
* ```typescript
1562+
* const gridVirtState = this.grid1.virtualizationState;
1563+
* ```
1564+
* @memberof IgxGridBaseComponent
1565+
*/
1566+
get virtualizationState() {
1567+
return this.verticalScrollContainer.state;
1568+
}
1569+
1570+
/**
1571+
* @hidden
1572+
*/
1573+
set virtualizationState(state) {
1574+
this.verticalScrollContainer.state = state;
1575+
}
1576+
15591577
/**
15601578
* Emitted when a new chunk of data is loaded from virtualization.
15611579
* ```typescript

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

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,52 @@ describe('IgxGrid - Advanced Filtering', () => {
380380
.toBe(false, 'Button icon indicates there is active filtering.');
381381
}));
382382

383+
it('Should correctly display header name in select dropdown and in chip expression.', fakeAsync(() => {
384+
// Open Advanced Filtering dialog.
385+
GridFunctions.clickAdvancedFilteringButton(fix);
386+
fix.detectChanges();
387+
388+
// Click the initial 'Add And Group' button.
389+
const addAndGroupButton = GridFunctions.getAdvancedFilteringInitialAddGroupButtons(fix)[0];
390+
addAndGroupButton.click();
391+
tick(100);
392+
fix.detectChanges();
393+
394+
// Open column dropdown and verify header name is displayed for first item
395+
GridFunctions.clickAdvancedFilteringColumnSelect(fix);
396+
fix.detectChanges();
397+
const dropdownItems = GridFunctions.getAdvancedFilteringSelectDropdownItems(fix);
398+
expect(dropdownItems[0].innerText).toBe('HeaderID');
399+
400+
selectColumnInEditModeExpression(fix, 0); // Select 'HeaderID' column
401+
selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator.
402+
const input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input');
403+
sendInputNativeElement(fix, input, 'a'); // Type filter value.
404+
405+
// Commit the populated expression.
406+
GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix);
407+
fix.detectChanges();
408+
409+
// Verify header name in chip text
410+
verifyExpressionChipContent(fix, [0], 'HeaderID', 'Contains', 'a');
411+
412+
// Apply the filters.
413+
GridFunctions.clickAdvancedFilteringApplyButton(fix);
414+
fix.detectChanges();
415+
416+
// Close Advanced Filtering dialog.
417+
GridFunctions.clickAdvancedFilteringCancelButton(fix);
418+
tick(100);
419+
fix.detectChanges();
420+
421+
// Open Advanced Filtering dialog again.
422+
GridFunctions.clickAdvancedFilteringButton(fix);
423+
fix.detectChanges();
424+
425+
// Verify header name in chip text
426+
verifyExpressionChipContent(fix, [0], 'HeaderID', 'Contains', 'a');
427+
}));
428+
383429
it('Should correctly filter by a \'string\' column through UI.', fakeAsync(() => {
384430
// Test prerequisites
385431
grid.height = '800px';
@@ -894,7 +940,7 @@ describe('IgxGrid - Advanced Filtering', () => {
894940
fix.detectChanges();
895941
const dropdownItems = GridFunctions.getAdvancedFilteringSelectDropdownItems(fix);
896942
expect(dropdownItems.length).toBe(3);
897-
expect(dropdownItems[0].innerText).toBe('ID');
943+
expect(dropdownItems[0].innerText).toBe('HeaderID');
898944
expect(dropdownItems[1].innerText).toBe('ProductName');
899945
expect(dropdownItems[2].innerText).toBe('Another Field');
900946
}));

projects/igniteui-angular/src/lib/grids/grid/grid.component.ts

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -172,24 +172,6 @@ export class IgxGridComponent extends IgxGridBaseComponent implements IGridDataB
172172
this._filteredData = value;
173173
}
174174

175-
/**
176-
* Returns the state of the grid virtualization, including the start index and how many records are rendered.
177-
* ```typescript
178-
* const gridVirtState = this.grid1.virtualizationState;
179-
* ```
180-
* @memberof IgxGridComponent
181-
*/
182-
get virtualizationState() {
183-
return this.verticalScrollContainer.state;
184-
}
185-
186-
/**
187-
* @hidden
188-
*/
189-
set virtualizationState(state) {
190-
this.verticalScrollContainer.state = state;
191-
}
192-
193175
/**
194176
* Sets the total number of records in the data source.
195177
* This property is required for remote grid virtualization to function when it is bound to remote data.

projects/igniteui-angular/src/lib/select/select.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
[attr.aria-owns]="this.listId"
1717
[attr.aria-activedescendant]="!this.collapsed ? this.focusedItem?.id : null"
1818
(blur)="onBlur()"
19+
(focus)="onFocus()"
1920
/>
2021
<ng-container ngProjectAs="igx-suffix">
2122
<ng-content select="igx-suffix,[igxSuffix]"></ng-content>

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

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { IgxInputState } from './../directives/input/input.directive';
22
import { Component, ViewChild, DebugElement } from '@angular/core';
33
import { async, TestBed, tick, fakeAsync } from '@angular/core/testing';
4-
import { FormsModule, FormGroup, FormBuilder, FormControl, Validators, ReactiveFormsModule, NgForm } from '@angular/forms';
4+
import { FormsModule, FormGroup, FormBuilder, FormControl, Validators, ReactiveFormsModule, NgForm, NgControl } from '@angular/forms';
55
import { By } from '@angular/platform-browser';
6-
import { IgxDropDownModule } from '../drop-down/index';
6+
import { IgxDropDownModule, IgxDropDownItemComponent } from '../drop-down/index';
77
import { IgxIconModule } from '../icon/index';
88
import { IgxInputGroupModule } from '../input-group/index';
99
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
@@ -604,6 +604,24 @@ describe('igxSelect', () => {
604604
expect(inputGroupWithRequiredAsterisk).toBeDefined();
605605
}));
606606

607+
it('Should have correctly bound focus and blur handlers', () => {
608+
const fix = TestBed.createComponent(IgxSelectTemplateFormComponent);
609+
fix.detectChanges();
610+
select = fix.componentInstance.select;
611+
const input = fix.debugElement.query(By.css(`.${CSS_CLASS_INPUT}`));
612+
613+
spyOn(select, 'onFocus');
614+
spyOn(select, 'onBlur');
615+
616+
input.triggerEventHandler('focus', {});
617+
expect(select.onFocus).toHaveBeenCalled();
618+
expect(select.onFocus).toHaveBeenCalledWith();
619+
620+
input.triggerEventHandler('blur', {});
621+
expect(select.onBlur).toHaveBeenCalled();
622+
expect(select.onFocus).toHaveBeenCalledWith();
623+
});
624+
607625
// Bug #6025 Select does not disable in reactive form
608626
it('Should disable when form is disabled', fakeAsync(() => {
609627
const fix = TestBed.createComponent(IgxSelectReactiveFormComponent);
@@ -2394,6 +2412,57 @@ describe('igxSelect', () => {
23942412
});
23952413
});
23962414

2415+
describe('igxSelect ControlValueAccessor Unit', () => {
2416+
let select: IgxSelectComponent;
2417+
it('Should correctly implement interface methods', () => {
2418+
const mockSelection = jasmine.createSpyObj('IgxSelectionAPIService', ['get', 'set', 'clear', 'first_item']);
2419+
const mockCdr = jasmine.createSpyObj('ChangeDetectorRef', ['detectChanges']);
2420+
const mockNgControl = jasmine.createSpyObj('NgControl', ['registerOnChangeCb', 'registerOnTouchedCb']);
2421+
const mockInjector = jasmine.createSpyObj('Injector', {
2422+
'get': mockNgControl
2423+
});
2424+
2425+
// init
2426+
select = new IgxSelectComponent(null, mockCdr, mockSelection, null, mockInjector);
2427+
select.ngOnInit();
2428+
select.registerOnChange(mockNgControl.registerOnChangeCb);
2429+
select.registerOnTouched(mockNgControl.registerOnTouchedCb);
2430+
expect(mockInjector.get).toHaveBeenCalledWith(NgControl, null);
2431+
2432+
// writeValue
2433+
expect(select.value).toBeUndefined();
2434+
select.writeValue('test');
2435+
expect(mockSelection.clear).toHaveBeenCalled();
2436+
expect(select.value).toBe('test');
2437+
2438+
// setDisabledState
2439+
select.setDisabledState(true);
2440+
expect(select.disabled).toBe(true);
2441+
select.setDisabledState(false);
2442+
expect(select.disabled).toBe(false);
2443+
2444+
// OnChange callback
2445+
const item = new IgxDropDownItemComponent(select, null, null, mockSelection);
2446+
item.value = 'itemValue';
2447+
select.selectItem(item);
2448+
expect(mockSelection.set).toHaveBeenCalledWith(select.id, new Set([item]));
2449+
expect(mockNgControl.registerOnChangeCb).toHaveBeenCalledWith('itemValue');
2450+
2451+
// OnTouched callback
2452+
select.onFocus();
2453+
expect(mockNgControl.registerOnTouchedCb).toHaveBeenCalledTimes(1);
2454+
2455+
select.input = {} as any;
2456+
spyOnProperty(select, 'collapsed').and.returnValue(true);
2457+
select.onBlur();
2458+
expect(mockNgControl.registerOnTouchedCb).toHaveBeenCalledTimes(2);
2459+
});
2460+
2461+
it('Should correctly handle ngControl validity', () => {
2462+
pending('Convert existing form test here');
2463+
});
2464+
});
2465+
23972466
@Component({
23982467
template: `
23992468
<igx-select #select [width]="'300px'" [height]="'200px'" [placeholder]="'Choose a city'" [(ngModel)]="value">

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,12 @@ export class IgxSelectComponent extends IgxDropDownComponent implements IgxSelec
202202
super(elementRef, cdr, selection, _displayDensityOptions);
203203
}
204204

205+
//#region ControlValueAccessor
206+
205207
/** @hidden @internal */
206208
private _onChangeCallback: (_: any) => void = noop;
209+
/** @hidden @internal */
210+
private _onTouchedCallback: () => void = noop;
207211

208212
/** @hidden @internal */
209213
public writeValue = (value: any) => {
@@ -216,12 +220,15 @@ export class IgxSelectComponent extends IgxDropDownComponent implements IgxSelec
216220
}
217221

218222
/** @hidden @internal */
219-
public registerOnTouched(fn: any): void { }
223+
public registerOnTouched(fn: any): void {
224+
this._onTouchedCallback = fn;
225+
}
220226

221227
/** @hidden @internal */
222228
public setDisabledState(isDisabled: boolean): void {
223229
this.disabled = isDisabled;
224230
}
231+
//#endregion
225232

226233
/** @hidden @internal */
227234
public getEditElement(): HTMLElement {
@@ -325,6 +332,7 @@ export class IgxSelectComponent extends IgxDropDownComponent implements IgxSelec
325332

326333
/** @hidden @internal */
327334
public onBlur(): void {
335+
this._onTouchedCallback();
328336
if (this.ngControl && !this.ngControl.valid) {
329337
this.input.valid = IgxInputState.INVALID;
330338
} else {
@@ -335,6 +343,11 @@ export class IgxSelectComponent extends IgxDropDownComponent implements IgxSelec
335343
}
336344
}
337345

346+
/** @hidden @internal */
347+
public onFocus(): void {
348+
this._onTouchedCallback();
349+
}
350+
338351
protected onStatusChanged() {
339352
if ((this.ngControl.control.touched || this.ngControl.control.dirty) &&
340353
(this.ngControl.control.validator || this.ngControl.control.asyncValidator)) {

projects/igniteui-angular/src/lib/test-utils/grid-samples.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1178,7 +1178,7 @@ export class IgxTestExcelFilteringDatePickerComponent extends IgxGridFilteringCo
11781178

11791179
@Component({
11801180
template: `<igx-grid [data]="data" height="500px" [allowAdvancedFiltering]="true" [showToolbar]="true">
1181-
<igx-column width="100px" [field]="'ID'" [header]="'ID'" [hasSummary]="true"></igx-column>
1181+
<igx-column width="100px" [field]="'ID'" [header]="'HeaderID'" [hasSummary]="true"></igx-column>
11821182
<igx-column width="100px" [field]="'ProductName'" dataType="string"></igx-column>
11831183
<igx-column width="100px" [field]="'Downloads'" dataType="number" [hasSummary]="true"></igx-column>
11841184
<igx-column width="100px" [field]="'Released'" dataType="boolean"></igx-column>

src/app/grid-filtering/grid-filtering.sample.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
exportExcelText="Export to Excel"
3131
exportCsvText="Export to CSV">
3232
<igx-column *ngFor="let c of columns" [field]="c.field"
33-
[header]="c.field"
33+
[header]="c.header"
3434
[movable]="c.movable"
3535
[groupable]="true"
3636
[resizable]="c.resizable"

src/app/grid-filtering/grid-filtering.sample.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,15 @@ export class GridFilteringComponent implements OnInit, AfterViewInit {
7878

7979
this.columns = [
8080
{ field: 'ID', width: 80, resizable: true, movable: true, type: 'string' },
81-
{ field: 'CompanyName', width: 150, resizable: true, movable: true, type: 'string'},
82-
{ field: 'ContactName', width: 150, resizable: true, movable: true, type: 'string' },
81+
{ field: 'CompanyName', header: 'Company Name', width: 175, resizable: true, movable: true, type: 'string'},
82+
{ field: 'ContactName', header: 'Contact Name', width: 175, resizable: true, movable: true, type: 'string' },
8383
{ field: 'Employees', width: 150, resizable: true, movable: true, type: 'number' },
84-
{ field: 'ContactTitle', width: 150, resizable: true, movable: true, type: 'string' },
85-
{ field: 'DateCreated', width: 150, resizable: true, movable: true, type: 'date' },
84+
{ field: 'ContactTitle', header: 'Contact Title', width: 150, resizable: true, movable: true, type: 'string' },
85+
{ field: 'DateCreated', header: 'Date Created', width: 150, resizable: true, movable: true, type: 'date' },
8686
{ field: 'Address', width: 150, resizable: true, movable: true, type: 'string' },
8787
{ field: 'City', width: 150, resizable: true, movable: true, type: 'string' },
8888
{ field: 'Region', width: 150, resizable: true, movable: true, type: 'string' },
89-
{ field: 'PostalCode', width: 150, resizable: true, movable: true, type: 'string' },
89+
{ field: 'PostalCode', header: 'Postal Code', width: 150, resizable: true, movable: true, type: 'string' },
9090
{ field: 'Phone', width: 150, resizable: true, movable: true, type: 'string' },
9191
{ field: 'Fax', width: 150, resizable: true, movable: true, type: 'string' },
9292
{ field: 'Contract', width: 150, resizable: true, movable: true, type: 'boolean' }

src/app/hierarchical-grid/hierarchical-grid.sample.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,9 @@ <h4 class="sample-title">Sample three</h4>
108108
<h4 class="sample-title">Sample 4</h4>
109109
<div class="sample-actions">
110110
<button igxButton="raised" (click)='LoadMoreColumns()'>Change columns runtime</button>
111+
<button igxButton="raised" (click)='changeData()'>Change data runtime</button>
111112
</div>
112-
<igx-hierarchical-grid [data]="localData" [autoGenerate]="false" [height]="'600px'" [width]="'800px'" #hGrid2>
113+
<igx-hierarchical-grid [data]="localData1" [autoGenerate]="false" [height]="'600px'" [width]="'800px'" #hGrid2>
113114
<igx-column field="ID" [resizable]="true" [pinned]="true" [filterable]='true'></igx-column>
114115
<igx-column field="ChildLevels" [resizable]="true" [groupable]='true'></igx-column>
115116
<igx-column field="ProductName" hasSummary='true'></igx-column>

src/app/hierarchical-grid/hierarchical-grid.sample.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ import {
1313
})
1414
export class HierarchicalGridSampleComponent {
1515
localData = [];
16+
localData1 = [];
17+
data1 = [];
18+
data2 = [];
1619
isRowSelectable = false;
1720
firstLevelExpanded = false;
1821
rootExpanded = false;
@@ -48,6 +51,9 @@ export class HierarchicalGridSampleComponent {
4851
{ label: 'comfortable', selected: this.density === 'comfortable', togglable: true }
4952
];
5053
this.localData = this.generateDataUneven(100, 3);
54+
this.data1 = this.localData.slice(0, 10);
55+
this.data2 = this.localData.slice(10, 20);
56+
this.localData1 = this.data1;
5157
this.localData[0].hasChild = false;
5258
this.localData[1].hasChild = false;
5359
this.localData[2].childData[0].hasChild = false;
@@ -135,4 +141,13 @@ export class HierarchicalGridSampleComponent {
135141
this.columns = ['Col1', 'Col2', 'Col3'];
136142
this.childColumns = ['ChildCol1', 'ChildCol2'];
137143
}
144+
145+
public changeData() {
146+
debugger;
147+
if (this.localData1 === this.data1) {
148+
this.localData1 = this.data2;
149+
} else {
150+
this.localData1 = this.data1;
151+
}
152+
}
138153
}

0 commit comments

Comments
 (0)