Skip to content

Commit cdf97dd

Browse files
MayaKirovaMKirovadkamburovChronosSF
authored
fix(grid): In case of external data change sync cell's formControl wi… (#12949)
* fix(grid): In case of external data change sync cell's formControl with new value. * chore(*): Add detect changes and test. * Use mark for check instead. * chore(*): Ensure test does not pollute data objects. * chore(*): Fix some test scenarios. * chore(*): A different approach with explicitly updating validity on data change. * chore(*): Add check in case setter is called before init. * chore(*): Fix test. * chore(*): Apply review comments. * chore(*): Additional small fix. --------- Co-authored-by: MKirova <MKirova@DEV-MKIROVA> Co-authored-by: Deyan Kamburov <[email protected]> Co-authored-by: Stamen Stoychev <[email protected]>
1 parent 9b22a7b commit cdf97dd

File tree

5 files changed

+53
-2
lines changed

5 files changed

+53
-2
lines changed

projects/igniteui-angular/src/lib/grids/grid/grid-validation.service.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ export class IgxGridValidationService {
3232
const value = resolveNestedPath(data || {}, col.field);
3333
const field = this.getFieldKey(col.field);
3434
const control = new FormControl(value, { updateOn: this.grid.validationTrigger });
35-
control.setValue(value);
3635
control.addValidators(col.validators);
3736
formGroup.addControl(field, control);
37+
control.setValue(value);
3838
}
3939
const args: IGridFormGroupCreatedEventArgs = {
4040
formGroup,
@@ -129,14 +129,30 @@ export class IgxGridValidationService {
129129
for (const key of keys) {
130130
const colKey = this.getFieldKey(key);
131131
const control = rowGroup?.get(colKey);
132-
if (control) {
132+
if (control && control.value !== rowData[key]) {
133133
control.setValue(rowData[key], { emitEvent: false });
134134
}
135135
}
136136

137137
this.updateStatus();
138138
}
139139

140+
/**
141+
* @hidden
142+
* @internal
143+
* Update validity based on new data.
144+
*/
145+
public updateAll(newData: any) {
146+
if (!newData || this._validityStates.size === 0) return;
147+
for (const rec of newData) {
148+
const rowId = rec[this.grid.primaryKey] || rec;
149+
if (this.getFormGroup(rowId)) {
150+
const recAggregatedData = this.grid.transactions.getAggregatedValue(rowId, true) || rec;
151+
this.update(rowId, recAggregatedData);
152+
}
153+
}
154+
}
155+
140156
/** Marks the associated record or field as touched.
141157
* @param key The id of the record that will be marked as touched.
142158
* @param field Optional. The field from the record that will be marked as touched. If not provided all fields will be touched.

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,31 @@ describe('IgxGrid - Validation #grid', () => {
285285
invalidRecords = grid.validation.getInvalid();
286286
expect(invalidRecords.length).toEqual(0);
287287
});
288+
289+
it('should update formControl state when grid data is updated.', () => {
290+
const grid = fixture.componentInstance.grid as IgxGridComponent;
291+
const originalDataCopy = JSON.parse(JSON.stringify(grid.data));
292+
293+
grid.data = JSON.parse(JSON.stringify(grid.data));
294+
let cell = grid.gridAPI.get_cell_by_visible_index(1, 1);
295+
UIInteractions.simulateDoubleClickAndSelectEvent(cell.element);
296+
cell.update('asd');
297+
fixture.detectChanges();
298+
grid.crudService.endEdit(true);
299+
fixture.detectChanges();
300+
301+
cell = grid.gridAPI.get_cell_by_visible_index(1, 1);
302+
//min length should be 4
303+
GridFunctions.verifyCellValid(cell, false);
304+
305+
grid.data = originalDataCopy;
306+
fixture.detectChanges();
307+
308+
cell = grid.gridAPI.get_cell_by_visible_index(1, 1);
309+
GridFunctions.verifyCellValid(cell, true);
310+
UIInteractions.simulateDoubleClickAndSelectEvent(cell.element);
311+
expect(cell.editValue).toBe(originalDataCopy[1].ProductName);
312+
});
288313
});
289314

290315
describe('Custom Validation - ', () => {

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,10 @@ export class IgxGridComponent extends IgxGridBaseDirective implements GridType,
382382
const dataLoaded = (!this._data || this._data.length === 0) && value && value.length > 0;
383383
this._data = value || [];
384384
this.summaryService.clearSummaryCache();
385+
if (!this._init) {
386+
this.validation.updateAll(this._data);
387+
}
388+
385389
if (this.shouldGenerate) {
386390
this.setupColumns();
387391
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,9 @@ export class IgxHierarchicalGridComponent extends IgxHierarchicalGridBaseDirecti
428428
public set data(value: any[] | null) {
429429
this._data = value || [];
430430
this.summaryService.clearSummaryCache();
431+
if (!this._init) {
432+
this.validation.updateAll(this._data);
433+
}
431434
if (this.shouldGenerate) {
432435
this.setupColumns();
433436
this.reflow();

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,9 @@ export class IgxTreeGridComponent extends IgxGridBaseDirective implements GridTy
351351
public set data(value: any[] | null) {
352352
this._data = value || [];
353353
this.summaryService.clearSummaryCache();
354+
if (!this._init) {
355+
this.validation.updateAll(this._data);
356+
}
354357
if (this.shouldGenerate) {
355358
this.setupColumns();
356359
}

0 commit comments

Comments
 (0)