Skip to content

Commit bfecbcc

Browse files
authored
Merge branch 'master' into rkaraivanov/ivy-rc6
2 parents f0fdd52 + b3b4917 commit bfecbcc

File tree

9 files changed

+119
-18
lines changed

9 files changed

+119
-18
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ export class IgxTemplateOutletDirective implements OnChanges {
3232
@Output()
3333
public onCachedViewLoaded = new EventEmitter<ICachedViewLoadedEventArgs>();
3434

35+
@Output()
36+
public onBeforeViewDetach = new EventEmitter<IViewChangeEventArgs>();
37+
3538
constructor(public _viewContainerRef: ViewContainerRef, private _zone: NgZone, public cdr: ChangeDetectorRef) {
3639
}
3740

@@ -66,6 +69,7 @@ export class IgxTemplateOutletDirective implements OnChanges {
6669
const prevIndex = this._viewRef ? this._viewContainerRef.indexOf(this._viewRef) : -1;
6770
// detach old and create new
6871
if (prevIndex !== -1) {
72+
this.onBeforeViewDetach.emit({ owner: this, view: this._viewRef, context: this.igxTemplateOutletContext });
6973
this._viewContainerRef.detach(prevIndex);
7074
}
7175
if (this.igxTemplateOutlet) {
@@ -92,9 +96,11 @@ export class IgxTemplateOutletDirective implements OnChanges {
9296
if (view !== this._viewRef) {
9397
if (owner._viewContainerRef.indexOf(view) !== -1) {
9498
// detach in case view it is attached somewhere else at the moment.
99+
this.onBeforeViewDetach.emit({ owner: this, view: this._viewRef, context: this.igxTemplateOutletContext });
95100
owner._viewContainerRef.detach(owner._viewContainerRef.indexOf(view));
96101
}
97102
if (this._viewRef && this._viewContainerRef.indexOf(this._viewRef) !== -1) {
103+
this.onBeforeViewDetach.emit({ owner: this, view: this._viewRef, context: this.igxTemplateOutletContext });
98104
this._viewContainerRef.detach(this._viewContainerRef.indexOf(this._viewRef));
99105
}
100106
this._viewRef = view;
@@ -113,6 +119,7 @@ export class IgxTemplateOutletDirective implements OnChanges {
113119
// then detach old view and insert the stored one with the matching template
114120
// after that update its context.
115121
if (this._viewContainerRef.length > 0) {
122+
this.onBeforeViewDetach.emit({ owner: this, view: this._viewRef, context: this.igxTemplateOutletContext });
116123
this._viewContainerRef.detach(this._viewContainerRef.indexOf(this._viewRef));
117124
}
118125

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6012,6 +6012,19 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements
60126012
return this.cellSelection !== GridSelectionMode.none;
60136013
}
60146014

6015+
public viewDetachHandler(args: ICachedViewLoadedEventArgs) {
6016+
const context = args.view.context;
6017+
if (context['templateID'] === 'dataRow') {
6018+
// some browsers (like FireFox and Edge) do not trigger onBlur when the focused element is detached from DOM
6019+
// hence we need to trigger it manually when cell is detached.
6020+
const row = this.getRowByIndex(context.index);
6021+
const focusedCell = row.cells.find(x => x.focused);
6022+
if (focusedCell) {
6023+
focusedCell.onBlur();
6024+
}
6025+
}
6026+
}
6027+
60156028
/**
60166029
* @hidden
60176030
*/

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

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -167,23 +167,34 @@ export class IgxGridNavigationService {
167167
}
168168

169169
public movePreviousEditable(rowIndex: number, currentColumnVisibleIndex: number) {
170-
const prevEditableColumnIndex = this.findNextEditable(MoveDirection.LEFT, currentColumnVisibleIndex - 1);
171-
if (prevEditableColumnIndex === -1 && this.grid.rowEditTabs.length) {
172-
// TODO: make gridAPI visible for internal use and remove cast to any
173-
(this.grid as any).gridAPI.submit_value();
174-
this.grid.rowEditTabs.last.element.nativeElement.focus();
175-
return;
170+
let prevEditableColumnIndex = this.findNextEditable(MoveDirection.LEFT, currentColumnVisibleIndex - 1);
171+
if (prevEditableColumnIndex === -1) {
172+
if (this.grid.rowEditTabs.length) {
173+
// TODO: make gridAPI visible for internal use and remove cast to any
174+
(this.grid as any).gridAPI.submit_value();
175+
this.grid.rowEditTabs.last.element.nativeElement.focus();
176+
return;
177+
} else {
178+
// In case when row edit template is empty select last editable cell
179+
prevEditableColumnIndex = this.grid.lastEditableColumnIndex;
180+
}
181+
176182
}
177183
this.focusEditableTarget(rowIndex, prevEditableColumnIndex);
178184
}
179185

180186
public moveNextEditable(rowIndex: number, currentColumnVisibleIndex: number) {
181-
const nextEditableColumnIndex = this.findNextEditable(MoveDirection.RIGHT, currentColumnVisibleIndex + 1);
182-
if (nextEditableColumnIndex === -1 && this.grid.rowEditTabs.length) {
183-
// TODO: make gridAPI visible for internal use and remove cast to any
184-
(this.grid as any).gridAPI.submit_value();
185-
this.grid.rowEditTabs.first.element.nativeElement.focus();
186-
return;
187+
let nextEditableColumnIndex = this.findNextEditable(MoveDirection.RIGHT, currentColumnVisibleIndex + 1);
188+
if (nextEditableColumnIndex === -1) {
189+
if ( this.grid.rowEditTabs.length) {
190+
// TODO: make gridAPI visible for internal use and remove cast to any
191+
(this.grid as any).gridAPI.submit_value();
192+
this.grid.rowEditTabs.first.element.nativeElement.focus();
193+
return;
194+
} else {
195+
// In case when row edit template is empty select first editable cell
196+
nextEditableColumnIndex = this.grid.firstEditableColumnIndex;
197+
}
187198
}
188199
this.focusEditableTarget(rowIndex, nextEditableColumnIndex);
189200
}

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

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ import {
2323
IgxGridWithEditingAndFeaturesComponent,
2424
IgxGridRowEditingWithoutEditableColumnsComponent,
2525
IgxGridCustomOverlayComponent,
26-
IgxGridRowEditingWithFeaturesComponent
26+
IgxGridRowEditingWithFeaturesComponent,
27+
IgxGridEmptyRowEditTemplateComponent
2728
} from '../../test-utils/grid-samples.spec';
2829
import { IgxGridTestComponent } from './grid.component.spec';
2930

@@ -45,7 +46,8 @@ describe('IgxGrid - Row Editing #grid', () => {
4546
IgxGridRowEditingWithoutEditableColumnsComponent,
4647
IgxGridTestComponent,
4748
IgxGridCustomOverlayComponent,
48-
IgxGridRowEditingWithFeaturesComponent
49+
IgxGridRowEditingWithFeaturesComponent,
50+
IgxGridEmptyRowEditTemplateComponent
4951
],
5052
imports: [
5153
NoopAnimationsModule, IgxGridModule]
@@ -1912,7 +1914,7 @@ describe('IgxGrid - Row Editing #grid', () => {
19121914

19131915
expect(parseInt(GridFunctions.getRowEditingBannerText(fix), 10)).toEqual(0);
19141916
fix.componentInstance.cellInEditMode.editValue = 'Spiro';
1915-
fix.componentInstance.moveNext(true);
1917+
UIInteractions.triggerKeyDownWithBlur('tab', cell.nativeElement, true);
19161918
tick(16);
19171919
fix.detectChanges();
19181920

@@ -1923,6 +1925,41 @@ describe('IgxGrid - Row Editing #grid', () => {
19231925
expect(grid.endEdit).toHaveBeenCalled();
19241926
expect(grid.endEdit).toHaveBeenCalledTimes(1);
19251927
}));
1928+
1929+
it('Empty template', fakeAsync(() => {
1930+
const fix = TestBed.createComponent(IgxGridEmptyRowEditTemplateComponent);
1931+
fix.detectChanges();
1932+
tick(16);
1933+
1934+
const grid = fix.componentInstance.grid;
1935+
let cell = grid.getCellByColumn(0, 'ProductName');
1936+
UIInteractions.triggerKeyDownEvtUponElem('f2', cell.nativeElement, true);
1937+
1938+
fix.detectChanges();
1939+
tick(16);
1940+
1941+
cell.editValue = 'Spiro';
1942+
UIInteractions.triggerKeyDownEvtUponElem('tab', cell.nativeElement, true);
1943+
1944+
fix.detectChanges();
1945+
tick(16);
1946+
fix.detectChanges();
1947+
tick(16);
1948+
1949+
expect(cell.editMode).toBe(false);
1950+
cell = grid.getCellByColumn(0, 'ReorderLevel');
1951+
expect(cell.editMode).toBe(true);
1952+
1953+
UIInteractions.triggerKeyDownEvtUponElem('tab', cell.nativeElement, true, false, true);
1954+
fix.detectChanges();
1955+
tick(16);
1956+
fix.detectChanges();
1957+
tick(16);
1958+
1959+
expect(cell.editMode).toBe(false);
1960+
cell = grid.getCellByColumn(0, 'ProductName');
1961+
expect(cell.editMode).toBe(true);
1962+
}));
19261963
});
19271964

19281965
describe('Transaction', () => {

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@
122122
[igxTemplateOutletContext]='getContext(rowData, rowIndex)'
123123
(onCachedViewLoaded)='cachedViewLoaded($event)'
124124
(onViewCreated)='viewCreatedHandler($event)'
125-
(onViewMoved)='viewMovedHandler($event)'>
125+
(onViewMoved)='viewMovedHandler($event)'
126+
(onBeforeViewDetach)='viewDetachHandler($event)'>
126127
</ng-template>
127128
</ng-template>
128129
<ng-template #record_template let-rowIndex="index" let-rowData>

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@
108108
<ng-template
109109
[igxTemplateOutlet]='(isHierarchicalRecord(rowData) ? hierarchical_record_template : (isChildGridRecord(rowData) && isExpanded(rowData) ? child_record_template : hierarchical_record_template))'
110110
[igxTemplateOutletContext]='getContext(rowData)' (onViewCreated)='viewCreatedHandler($event)'
111-
(onViewMoved)='viewMovedHandler($event)' (onCachedViewLoaded)='cachedViewLoaded($event)'></ng-template>
111+
(onViewMoved)='viewMovedHandler($event)' (onCachedViewLoaded)='cachedViewLoaded($event)'
112+
(onBeforeViewDetach)='viewDetachHandler($event)'></ng-template>
112113
<!-- <ng-container *igxTemplateOutlet="(isHierarchicalRecord(rowData) ? hierarchical_record_template : (isChildGridRecord(rowData) && isExpanded(rowData) ? child_record_template : hierarchical_record_template)); context: getContext(rowData)"></ng-container> -->
113114
</ng-template>
114115
<ng-container *ngTemplateOutlet="template"></ng-container>

projects/igniteui-angular/src/lib/grids/row-drag.directive.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { fromEvent, Subscription } from 'rxjs';
55
import { IgxRowDirective, IgxGridBaseDirective } from './grid';
66
import { IRowDragStartEventArgs, IRowDragEndEventArgs } from './common/events';
77
import { GridType } from './common/grid.interface';
8+
import { IgxHierarchicalRowComponent } from './hierarchical-grid/hierarchical-row.component';
89

910

1011
const ghostBackgroundClass = 'igx-grid__tr--ghost';
@@ -107,6 +108,15 @@ export class IgxRowDragDirective extends IgxDragDirective implements OnDestroy {
107108
};
108109
super.createGhost(pageX, pageY, this.row.nativeElement);
109110

111+
// check if there is an expander icon and create the ghost at the corresponding position
112+
if (this.isHierarchicalGrid) {
113+
const row = this.row as IgxHierarchicalRowComponent;
114+
if (row.expander) {
115+
const expanderWidth = row.expander.nativeElement.getBoundingClientRect().width;
116+
this._ghostHostX += expanderWidth;
117+
}
118+
}
119+
110120
const ghost = this.ghostElement;
111121

112122
const gridRect = this.row.grid.nativeElement.getBoundingClientRect();
@@ -145,6 +155,10 @@ export class IgxRowDragDirective extends IgxDragDirective implements OnDestroy {
145155
}
146156
this.endDragging();
147157
}
158+
159+
private get isHierarchicalGrid() {
160+
return this.row.grid.nativeElement.tagName.toLowerCase() === 'igx-hierarchical-grid';
161+
}
148162
}
149163

150164
/**

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@
9595

9696
<ng-template [igxTemplateOutlet]='isSummaryRow(rowData) ? summary_template : record_template'
9797
[igxTemplateOutletContext]='getContext(rowData, rowIndex)'
98-
(onCachedViewLoaded)='cachedViewLoaded($event)'>
98+
(onCachedViewLoaded)='cachedViewLoaded($event)'
99+
(onBeforeViewDetach)='viewDetachHandler($event)'>
99100
</ng-template>
100101
</ng-template>
101102
<ng-container *ngTemplateOutlet="template"></ng-container>

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,6 +1481,22 @@ export class IgxGridCustomOverlayComponent extends BasicGridComponent {
14811481
}
14821482
}
14831483

1484+
@Component({
1485+
template: `
1486+
<igx-grid #grid [data]="data" [primaryKey]="'ProductID'" width="700px" height="400px" [rowEditable]="true">
1487+
<igx-column field="ProductID" header="Product ID"></igx-column>
1488+
<igx-column field="ReorderLevel" header="Reorder Lever" [dataType]="'number'" [editable]="true" width="100px"></igx-column>
1489+
<igx-column field="ProductName" header="Product Name" [dataType]="'string'" width="150px"></igx-column>
1490+
<igx-column field="OrderDate" header="Order Date" [dataType]="'date'" width="150px" [editable]="false"></igx-column>
1491+
<ng-template igxRowEdit >
1492+
</ng-template>
1493+
</igx-grid>
1494+
`
1495+
})
1496+
export class IgxGridEmptyRowEditTemplateComponent extends BasicGridComponent {
1497+
public data = SampleTestData.foodProductData();
1498+
}
1499+
14841500
@Component({
14851501
template: `
14861502
<igx-grid #grid [data]="data" [primaryKey]="'ProductID'" width="900px" height="900px" [rowEditable]="true"

0 commit comments

Comments
 (0)