Skip to content

Commit 72dbf38

Browse files
committed
Merge pivot-grid-master into skrastev/pivot-grid-resize.
2 parents e62aa17 + 9bac3bc commit 72dbf38

34 files changed

+688
-391
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ All notable changes for each version of this project will be documented in this
3333
<igx-column field="Age"></igx-column>
3434
</igx-grid>
3535
```
36+
- Scrolling with the mouse wheel over cells with templates that include scrollable containers now correctly scroll these inner containers before the grid body scrolls.
3637

3738
## 13.0.5
3839

projects/igniteui-angular/src/lib/core/styles/components/grid/_grid-component.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,10 @@
577577
@extend %igx-grid__tr-pivot-group !optional
578578
}
579579

580+
@include e(tr-header-row) {
581+
@extend %igx-grid__tr-header-row !optional;
582+
}
583+
580584
@include e(tr-pivot-toggle-icons) {
581585
@extend %igx-grid__tr-pivot-toggle-icons !optional;
582586
}

projects/igniteui-angular/src/lib/core/styles/components/grid/_grid-theme.scss

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2977,6 +2977,14 @@
29772977
%igx-grid__tr-pivot-toggle-icons {
29782978
display: inline-flex !important;
29792979
}
2980+
2981+
%igx-grid__tr-header-row {
2982+
igx-pivot-row-dimension-header-group {
2983+
igx-pivot-row-dimension-header {
2984+
align-items: center;
2985+
}
2986+
}
2987+
}
29802988
// Pivot grid END
29812989
}
29822990

projects/igniteui-angular/src/lib/directives/for-of/for_of.directive.ts

Lines changed: 59 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,10 @@ export class IgxForOfDirective<T> implements OnInit, OnChanges, DoCheck, OnDestr
414414

415415
if (this.igxForScrollOrientation === 'vertical') {
416416
this.dc.instance._viewContainer.element.nativeElement.style.top = '0px';
417-
this.scrollComponent = vc.createComponent(VirtualHelperComponent).instance;
417+
this.scrollComponent = this.syncScrollService.getScrollMaster(this.igxForScrollOrientation);
418+
if (!this.scrollComponent || !this.document.contains(this.scrollComponent.elementRef.nativeElement)) {
419+
this.scrollComponent = vc.createComponent(VirtualHelperComponent).instance
420+
}
418421
this._maxHeight = this._calcMaxBrowserHeight();
419422
this.scrollComponent.size = this.igxForOf ? this._calcHeight() : 0;
420423
this.syncScrollService.setScrollMaster(this.igxForScrollOrientation, this.scrollComponent);
@@ -721,6 +724,34 @@ export class IgxForOfDirective<T> implements OnInit, OnChanges, DoCheck, OnDestr
721724
return scroll;
722725
}
723726

727+
/**
728+
* Returns the index of the element at the specified offset.
729+
* ```typescript
730+
* this.parentVirtDir.getIndexAtScroll(100);
731+
* ```
732+
*/
733+
public getIndexAtScroll(scrollOffset: number) {
734+
return this.getIndexAt(scrollOffset, this.sizesCache);
735+
}
736+
/**
737+
* Returns whether the target index is outside the view.
738+
* ```typescript
739+
* this.parentVirtDir.isIndexOutsideView(10);
740+
* ```
741+
*/
742+
public isIndexOutsideView(index: number) {
743+
const targetNode = index >= this.state.startIndex && index <= this.state.startIndex + this.state.chunkSize ?
744+
this._embeddedViews.map(view =>
745+
view.rootNodes.find(node => node.nodeType === Node.ELEMENT_NODE) || view.rootNodes[0].nextElementSibling)[index - this.state.startIndex] : null;
746+
const rowHeight = this.getSizeAt(index);
747+
const containerSize = parseInt(this.igxForContainerSize, 10);
748+
const containerOffset = -(this.scrollPosition - this.sizesCache[this.state.startIndex]);
749+
const endTopOffset = targetNode ? targetNode.offsetTop + rowHeight + containerOffset : containerSize + rowHeight;
750+
return !targetNode || targetNode.offsetTop < Math.abs(containerOffset)
751+
|| containerSize && endTopOffset - containerSize > 5;
752+
}
753+
754+
724755
/**
725756
* @hidden
726757
* Function that recalculates and updates cache sizes.
@@ -1115,20 +1146,16 @@ export class IgxForOfDirective<T> implements OnInit, OnChanges, DoCheck, OnDestr
11151146
protected initSizesCache(items: any[]): number {
11161147
let totalSize = 0;
11171148
let size = 0;
1118-
const dimension = this.igxForScrollOrientation === 'horizontal' ?
1119-
this.igxForSizePropName : 'height';
1149+
const dimension = this.igxForSizePropName || 'height';
11201150
let i = 0;
11211151
this.sizesCache = [];
11221152
this.heightCache = [];
11231153
this.sizesCache.push(0);
11241154
const count = this.isRemote ? this.totalItemCount : items.length;
11251155
for (i; i < count; i++) {
1126-
if (dimension === 'height') {
1127-
// cols[i][dimension] = parseInt(this.igxForItemSize, 10) || 0;
1128-
size = parseInt(this.igxForItemSize, 10) || 0;
1156+
size = this._getItemSize(items[i], dimension);
1157+
if (this.igxForScrollOrientation === 'vertical') {
11291158
this.heightCache.push(size);
1130-
} else {
1131-
size = this._getItemSize(items[i], dimension);
11321159
}
11331160
totalSize += size;
11341161
this.sizesCache.push(totalSize);
@@ -1359,6 +1386,11 @@ export class IgxForOfDirective<T> implements OnInit, OnChanges, DoCheck, OnDestr
13591386
this._virtScrollTop = realPercentScrolled * maxVirtScrollTop;
13601387
}
13611388

1389+
protected _getItemSize(item, dimension: string): number {
1390+
const dim = item ? item[dimension] : null;
1391+
return typeof dim === 'number' ? dim : parseInt(this.igxForItemSize, 10) || 0;
1392+
}
1393+
13621394
private _updateVScrollOffset() {
13631395
let scrollOffset = 0;
13641396
let currentScrollTop = this.scrollPosition;
@@ -1380,10 +1412,6 @@ export class IgxForOfDirective<T> implements OnInit, OnChanges, DoCheck, OnDestr
13801412
this.dc.instance._viewContainer.element.nativeElement.style.left = -scrollOffset + 'px';
13811413
}
13821414

1383-
private _getItemSize(item, dimension: string): number {
1384-
const dim = item[dimension];
1385-
return typeof dim === 'number' ? dim : parseInt(this.igxForItemSize, 10) || 0;
1386-
}
13871415

13881416
private _adjustScrollPositionAfterSizeChange(sizeDiff) {
13891417
// if data has been changed while container is scrolled
@@ -1436,10 +1464,14 @@ export class IgxGridForOfDirective<T> extends IgxForOfDirective<T> implements On
14361464
* @internal
14371465
*/
14381466
public get sizesCache(): number[] {
1439-
if (this.syncService.isMaster(this)) {
1467+
if (this.igxForScrollOrientation === 'horizontal') {
1468+
if (this.syncService.isMaster(this)) {
1469+
return this._sizesCache;
1470+
}
1471+
return this.syncService.sizesCache(this.igxForScrollOrientation);
1472+
} else {
14401473
return this._sizesCache;
14411474
}
1442-
return this.syncService.sizesCache(this.igxForScrollOrientation);
14431475
}
14441476
/**
14451477
* @hidden
@@ -1450,7 +1482,7 @@ export class IgxGridForOfDirective<T> extends IgxForOfDirective<T> implements On
14501482
}
14511483

14521484
protected get itemsDimension() {
1453-
return this.igxForScrollOrientation === 'horizontal' ? this.igxForSizePropName : 'height';
1485+
return this.igxForSizePropName || 'height';
14541486
}
14551487

14561488
/**
@@ -1578,10 +1610,9 @@ export class IgxGridForOfDirective<T> extends IgxForOfDirective<T> implements On
15781610

15791611
protected getItemSize(item) {
15801612
let size = 0;
1581-
const dimension = this.igxForScrollOrientation === 'horizontal' ?
1582-
this.igxForSizePropName : 'height';
1583-
if (dimension === 'height') {
1584-
size = parseInt(this.igxForItemSize, 10) || 0;
1613+
const dimension = this.igxForSizePropName || 'height';
1614+
if (this.igxForScrollOrientation === 'vertical') {
1615+
size = this._getItemSize(item, dimension);
15851616
if (item && item.summaries) {
15861617
size = item.max;
15871618
} else if (item && item.groups && item.height) {
@@ -1594,7 +1625,7 @@ export class IgxGridForOfDirective<T> extends IgxForOfDirective<T> implements On
15941625
}
15951626

15961627
protected initSizesCache(items: any[]): number {
1597-
if (!this.syncService.isMaster(this)) {
1628+
if (!this.syncService.isMaster(this) && this.igxForScrollOrientation === 'horizontal') {
15981629
const masterSizesCache = this.syncService.sizesCache(this.igxForScrollOrientation);
15991630
return masterSizesCache[masterSizesCache.length - 1];
16001631
}
@@ -1607,7 +1638,7 @@ export class IgxGridForOfDirective<T> extends IgxForOfDirective<T> implements On
16071638
const count = this.isRemote ? this.totalItemCount : items.length;
16081639
for (i; i < count; i++) {
16091640
size = this.getItemSize(items[i]);
1610-
if (this.itemsDimension === 'height') {
1641+
if (this.igxForScrollOrientation === 'vertical') {
16111642
this.heightCache.push(size);
16121643
}
16131644
totalSize += size;
@@ -1744,10 +1775,15 @@ export class IgxGridForOfDirective<T> extends IgxForOfDirective<T> implements On
17441775
* @hidden
17451776
*/
17461777
protected _calcMaxChunkSize(): number {
1747-
if (this.syncService.isMaster(this)) {
1778+
if (this.igxForScrollOrientation === 'horizontal') {
1779+
if (this.syncService.isMaster(this)) {
1780+
return super._calcMaxChunkSize();
1781+
}
1782+
return this.syncService.chunkSize(this.igxForScrollOrientation);
1783+
} else {
17481784
return super._calcMaxChunkSize();
17491785
}
1750-
return this.syncService.chunkSize(this.igxForScrollOrientation);
1786+
17511787
}
17521788
}
17531789

projects/igniteui-angular/src/lib/directives/scroll-inertia/scroll_inertia.directive.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ export class IgxScrollInertiaDirective implements OnInit, OnDestroy {
138138
scrollDeltaY = this.calcAxisCoords(deltaScaledY, -1, 1);
139139
}
140140

141+
if (evt.composedPath && this.didChildScroll(evt, scrollDeltaX, scrollDeltaY)) {
142+
return;
143+
}
144+
141145
if (scrollDeltaX && this.IgxScrollInertiaDirection === 'horizontal') {
142146
const nextLeft = this._startX + scrollDeltaX * scrollStep;
143147
if (!smoothing) {
@@ -186,6 +190,36 @@ export class IgxScrollInertiaDirective implements OnInit, OnDestroy {
186190
}
187191
}
188192

193+
/**
194+
* @hidden
195+
* Checks if the wheel event would have scrolled an element under the display container
196+
* in DOM tree so that it can correctly be ignored until that element can no longer be scrolled.
197+
*/
198+
protected didChildScroll(evt, scrollDeltaX, scrollDeltaY): boolean {
199+
const path = evt.composedPath();
200+
let i = 0;
201+
while (i < path.length && path[i].localName !== 'igx-display-container') {
202+
const e = path[i++];
203+
if (e.scrollHeight > e.clientHeight) {
204+
if (scrollDeltaY > 0 && e.scrollHeight - Math.abs(Math.round(e.scrollTop)) !== e.clientHeight) {
205+
return true;
206+
}
207+
if (scrollDeltaY < 0 && e.scrollTop !== 0) {
208+
return true;
209+
}
210+
}
211+
if (e.scrollWidth > e.clientWidth) {
212+
if (scrollDeltaX > 0 && e.scrollWidth - Math.abs(Math.round(e.scrollLeft)) !== e.clientWidth) {
213+
return true;
214+
}
215+
if (scrollDeltaX < 0 && e.scrollLeft !== 0) {
216+
return true;
217+
}
218+
}
219+
}
220+
return false;
221+
}
222+
189223
/**
190224
* @hidden
191225
* Function that is called the first moment we start interacting with the content on a touch device

projects/igniteui-angular/src/lib/grids/columns/column.component.ts

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1790,7 +1790,7 @@ export class IgxColumnComponent implements AfterContentInit, OnDestroy, ColumnTy
17901790
*/
17911791
public getGridTemplate(isRow: boolean): string {
17921792
if (isRow) {
1793-
const rowsCount = this.grid.multiRowLayoutRowSize;
1793+
const rowsCount = !this.grid.isPivot ? this.grid.multiRowLayoutRowSize : this.children.length - 1;
17941794
return `repeat(${rowsCount},1fr)`;
17951795
} else {
17961796
return this.getColumnSizesString(this.children);
@@ -2312,23 +2312,7 @@ export class IgxColumnComponent implements AfterContentInit, OnDestroy, ColumnTy
23122312
* Returns the width and padding of a header cell.
23132313
*/
23142314
public getHeaderCellWidths() {
2315-
const range = this.grid.document.createRange();
2316-
2317-
// We do not cover cases where there are children with width 100% and etc,
2318-
// because then we try to get new column size, based on header content, which is sized based on column size...
2319-
const headerWidth = this.platform.getNodeSizeViaRange(range,
2320-
this.headerCell.nativeElement,
2321-
this.headerGroup.nativeElement);
2322-
2323-
const headerStyle = this.grid.document.defaultView.getComputedStyle(this.headerCell.nativeElement);
2324-
const headerPadding = parseFloat(headerStyle.paddingLeft) + parseFloat(headerStyle.paddingRight) +
2325-
parseFloat(headerStyle.borderRightWidth);
2326-
2327-
// Take into consideration the header group element, since column pinning applies borders to it if its not a columnGroup.
2328-
const headerGroupStyle = this.grid.document.defaultView.getComputedStyle(this.headerGroup.nativeElement);
2329-
const borderSize = !this.parent ? parseFloat(headerGroupStyle.borderRightWidth) + parseFloat(headerGroupStyle.borderLeftWidth) : 0;
2330-
2331-
return { width: Math.ceil(headerWidth), padding: Math.ceil(headerPadding + borderSize) };
2315+
return this.grid.getHeaderCellWidth(this.headerCell.nativeElement);
23322316
}
23332317

23342318
/**

projects/igniteui-angular/src/lib/grids/common/grid.interface.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ export interface GridType extends IGridDataBindable {
404404
hasColumnGroups: boolean;
405405
hasEditableColumns: boolean;
406406
uniqueColumnValuesStrategy: (column: ColumnType, tree: FilteringExpressionsTree, done: (values: any[]) => void) => void;
407+
getHeaderCellWidth: (element: HTMLElement) => ISizeInfo;
407408

408409
cdr: ChangeDetectorRef;
409410
document: Document;
@@ -644,3 +645,8 @@ export interface GridSVGIcon {
644645
name: string;
645646
value: string;
646647
}
648+
649+
export interface ISizeInfo {
650+
width: number,
651+
padding: number
652+
}

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

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ import {
123123
IPinColumnCancellableEventArgs
124124
} from './common/events';
125125
import { IgxAdvancedFilteringDialogComponent } from './filtering/advanced-filtering/advanced-filtering-dialog.component';
126-
import { ColumnType, GridServiceType, GridType, IGX_GRID_SERVICE_BASE, RowType } from './common/grid.interface';
126+
import { ColumnType, GridServiceType, GridType, IGX_GRID_SERVICE_BASE, ISizeInfo, RowType } from './common/grid.interface';
127127
import { DropPosition } from './moving/moving.service';
128128
import { IgxHeadSelectorDirective, IgxRowSelectorDirective } from './selection/row-selectors';
129129
import { IgxColumnComponent } from './columns/column.component';
@@ -2960,7 +2960,7 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
29602960
@Inject(IGX_GRID_SERVICE_BASE) public gridAPI: GridServiceType,
29612961
protected transactionFactory: IgxFlatTransactionFactory,
29622962
private elementRef: ElementRef<HTMLElement>,
2963-
private zone: NgZone,
2963+
protected zone: NgZone,
29642964
@Inject(DOCUMENT) public document: any,
29652965
public cdr: ChangeDetectorRef,
29662966
protected resolver: ComponentFactoryResolver,
@@ -3883,6 +3883,26 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
38833883
return this.width === null || diff >= 0;
38843884
}
38853885

3886+
/**
3887+
* @hidden @internal
3888+
* Gets the header cell inner width for auto-sizing.
3889+
*/
3890+
public getHeaderCellWidth(element: HTMLElement): ISizeInfo {
3891+
const range = this.document.createRange();
3892+
const headerWidth = this.platform.getNodeSizeViaRange(range,
3893+
element,
3894+
element.parentElement);
3895+
3896+
const headerStyle = this.document.defaultView.getComputedStyle(element);
3897+
const headerPadding = parseFloat(headerStyle.paddingLeft) + parseFloat(headerStyle.paddingRight) +
3898+
parseFloat(headerStyle.borderRightWidth);
3899+
3900+
// Take into consideration the header group element, since column pinning applies borders to it if its not a columnGroup.
3901+
const headerGroupStyle = this.document.defaultView.getComputedStyle(element.parentElement);
3902+
const borderSize = parseFloat(headerGroupStyle.borderRightWidth) + parseFloat(headerGroupStyle.borderLeftWidth);
3903+
return { width: Math.ceil(headerWidth), padding: Math.ceil(headerPadding + borderSize) };
3904+
}
3905+
38863906
/**
38873907
* @hidden @internal
38883908
* Gets the combined width of the columns that are specific to the enabled grid features. They are fixed.
@@ -6980,7 +7000,7 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
69807000
this.cdr.markForCheck();
69817001
}
69827002

6983-
private verticalScrollHandler(event) {
7003+
protected verticalScrollHandler(event) {
69847004
this.verticalScrollContainer.onScroll(event);
69857005
this.disableTransitions = true;
69867006

0 commit comments

Comments
 (0)