From 1b0bd8f20f0e5bfed387a39714d7598dd6ce5abe Mon Sep 17 00:00:00 2001 From: Yuriy K Date: Thu, 17 Mar 2022 18:19:31 +0300 Subject: [PATCH 1/7] pager - dont propagate button press --- .../src/lib/templates/plugin-pager-target.tpl.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/qgrid-ngx-theme-material/src/lib/templates/plugin-pager-target.tpl.html b/packages/qgrid-ngx-theme-material/src/lib/templates/plugin-pager-target.tpl.html index 41daa18f1..1f269cd89 100644 --- a/packages/qgrid-ngx-theme-material/src/lib/templates/plugin-pager-target.tpl.html +++ b/packages/qgrid-ngx-theme-material/src/lib/templates/plugin-pager-target.tpl.html @@ -3,7 +3,7 @@ - + Date: Fri, 8 Apr 2022 12:27:23 +0300 Subject: [PATCH 2/7] draft - pinned rows navigation --- packages/qgrid-core/src/cell/cell.selector.js | 4 +-- .../src/dom/selector/selector.factory.js | 32 +++++++++-------- .../src/dom/selector/selector.mark.js | 35 +++++++++++++------ .../src/dom/selector/selector.mediate.js | 8 +++-- packages/qgrid-core/src/dom/view.js | 5 +-- .../src/navigation/navigation.let.js | 13 ++++--- packages/qgrid-core/src/view/view.host.js | 17 ++++++--- .../src/lib/body/body-core.component.html | 5 +-- .../src/lib/body/td-core.directive.ts | 18 ++++++++-- .../cell-handler/cell-handler.component.ts | 7 ++-- .../src/lib/row/tr-core.directive.ts | 2 ++ 11 files changed, 99 insertions(+), 47 deletions(-) diff --git a/packages/qgrid-core/src/cell/cell.selector.js b/packages/qgrid-core/src/cell/cell.selector.js index bf4dd9511..9e5e8a549 100644 --- a/packages/qgrid-core/src/cell/cell.selector.js +++ b/packages/qgrid-core/src/cell/cell.selector.js @@ -51,9 +51,9 @@ export class CellSelector { } mapFromCells(items) { - const { table } = this; + const { model, table } = this; const result = []; - const rows = table.data.rows(); + const rows = model.row().pinTop.concat(model.scene().rows).concat(model.row().pinBottom); const columns = table.data.columns(); for (let item of items) { diff --git a/packages/qgrid-core/src/dom/selector/selector.factory.js b/packages/qgrid-core/src/dom/selector/selector.factory.js index 5c381dc7c..e4743a08b 100644 --- a/packages/qgrid-core/src/dom/selector/selector.factory.js +++ b/packages/qgrid-core/src/dom/selector/selector.factory.js @@ -17,31 +17,33 @@ export class SelectorFactory { const entries = selectorMark .select() - .map(({ element, rowRange, columnRange }) => ({ + .map(({ name, element, rowRange, columnRange }) => ({ + name, matrix: matrix.build(element), rowRange, columnRange })); const selectorFactory = context => { - return entries.map(entry => ({ - invoke: f => { - const unitFactory = new UnitFactory(entry.rowRange, entry.columnRange); - const selector = new Selector(entry.matrix, bag, unitFactory); + return entries.map(entry => ({ + invoke: f => { + const unitFactory = new UnitFactory(entry.rowRange, entry.columnRange); + const selector = new Selector(entry.matrix, bag, unitFactory); - const args = []; - args.push(selector); + const args = []; + args.push(selector); - if (context.hasOwnProperty('row')) { - args.push(context.row - entry.rowRange.start); - } + if (context.hasOwnProperty('row')) { + args.push(context.row - entry.rowRange.start); + } - if (context.hasOwnProperty('column')) { - args.push(context.column - entry.columnRange.start); - } + if (context.hasOwnProperty('column')) { + args.push(context.column - entry.columnRange.start); + } - return f(...args); - } + return f(...args); + }, + type: entry.name })); }; diff --git a/packages/qgrid-core/src/dom/selector/selector.mark.js b/packages/qgrid-core/src/dom/selector/selector.mark.js index 6e311c553..356110ccf 100644 --- a/packages/qgrid-core/src/dom/selector/selector.mark.js +++ b/packages/qgrid-core/src/dom/selector/selector.mark.js @@ -10,30 +10,43 @@ export class SelectorMark { select() { const result = []; const addNext = this.addFactory(result); - - addNext('left'); - addNext('mid'); - addNext('right'); - + if (this.name == 'body') { + addNext('left','top'); + addNext('mid','top'); + addNext('right','top'); + addNext('left','mid'); + addNext('mid','mid'); + addNext('right','mid'); + addNext('left','bottom'); + addNext('mid','bottom'); + addNext('right','bottom'); + } + else { + addNext('left', null); + addNext('mid', null); + addNext('right', null); + } return result; } addFactory(result) { const { model } = this; - const { rows } = model.scene(); const columnArea = model.scene().column.area; - return pin => { - const name = pin ? `${this.name}-${pin}` : this.name; + return (pinLR, pinTB) => { + const rows = pinTB == 'top' ? model.row().pinTop : pinTB == 'bottom' ? model.row().pinBottom : model.scene().rows; + const name = this.name + ((pinTB && pinTB !== 'mid') ? `-${pinTB}` : '') + (pinLR ? `-${pinLR}` : ''); const element = this.markup[name]; if (element) { - const prev = result[result.length - 1]; + const prev = pinLR === 'left' ? null : result[result.length - 1]; const columnStart = prev ? prev.columnRange.end : 0; - const columnCount = columnArea[pin].length; - const rowStart = 0; + const columnCount = columnArea[pinLR].length; + const rowStart = pinTB === 'mid' ? model.row().pinTop.length : pinTB === 'bottom' ? + model.row().pinTop.length + model.scene().rows.length : 0; const rowCount = rows.length; result.push({ + name: this.name + ((pinTB == 'top' || pinTB == 'bottom') ? `-${pinTB}` : ''), element, columnRange: new Range(columnStart, columnStart + columnCount), rowRange: new Range(rowStart, rowStart + rowCount) diff --git a/packages/qgrid-core/src/dom/selector/selector.mediate.js b/packages/qgrid-core/src/dom/selector/selector.mediate.js index 6fe4dbb3f..388abb5d0 100644 --- a/packages/qgrid-core/src/dom/selector/selector.mediate.js +++ b/packages/qgrid-core/src/dom/selector/selector.mediate.js @@ -9,7 +9,7 @@ export class SelectorMediator { } columnCount(rowIndex) { - const selectors = this.buildSelectors({ row: rowIndex }); + const selectors = this.buildSelectors({ row: rowIndex }).filter(x => x.type === 'body'); if (!selectors.length) { return 0; } @@ -34,8 +34,12 @@ export class SelectorMediator { if (!selectors.length) { return 0; } + + const rowCountTop = max(selectors.filter(x => x.type === 'body-top')?.map(s => s.invoke((s, columnIndex) => s.rowCount(columnIndex)))) ?? 0; + const rowCount = max(selectors.filter(x => x.type === 'body')?.map(s => s.invoke((s, columnIndex) => s.rowCount(columnIndex)))) ?? 0; + const rowCountBottom = max(selectors.filter(x => x.type === 'body-bottom')?.map(s => s.invoke((s, columnIndex) => s.rowCount(columnIndex)))) ?? 0; - return max(selectors.map(s => s.invoke((s, columnIndex) => s.rowCount(columnIndex)))); + return rowCountTop + rowCount + rowCountBottom; } rows(columnIndex) { diff --git a/packages/qgrid-core/src/dom/view.js b/packages/qgrid-core/src/dom/view.js index 164a39f7f..ad0adb93c 100644 --- a/packages/qgrid-core/src/dom/view.js +++ b/packages/qgrid-core/src/dom/view.js @@ -44,8 +44,9 @@ export class View extends Unit { } isFocused() { - return this.getElementsCore('body') - .some(element => this.isFocusedCore(element)); + return this.getElementsCore('body').some(element => this.isFocusedCore(element)) || + this.getElementsCore('body-top').some(element => this.isFocusedCore(element)) || + this.getElementsCore('body-bottom').some(element => this.isFocusedCore(element)); } addLayer(name) { diff --git a/packages/qgrid-core/src/navigation/navigation.let.js b/packages/qgrid-core/src/navigation/navigation.let.js index c72e20cea..fa6490a4e 100644 --- a/packages/qgrid-core/src/navigation/navigation.let.js +++ b/packages/qgrid-core/src/navigation/navigation.let.js @@ -11,9 +11,9 @@ export class NavigationLet { this.plugin = plugin; const navigation = new Navigation(model, table); - let focusBlurs = []; + let focusBlurs = []; - shortcut.register(navigation.commands); + shortcut.register(navigation.commands); this.focus = new Command({ source: 'navigation.view', @@ -168,10 +168,15 @@ export class NavigationLet { } scroll(view, target) { - const { model } = this.plugin; + const { model, table } = this.plugin; const { scroll } = model; Fastdom.measure(() => { - const tr = target.rect(); + const tr = target.rect(); + + //move this code + if (table.body.cell(target.rowIndex, target.columnIndex).model().td.pin !== 'body') { + return; + } const vr = view.rect('body-mid'); const state = {}; diff --git a/packages/qgrid-core/src/view/view.host.js b/packages/qgrid-core/src/view/view.host.js index c29c00b88..397da4d02 100644 --- a/packages/qgrid-core/src/view/view.host.js +++ b/packages/qgrid-core/src/view/view.host.js @@ -206,15 +206,22 @@ export class ViewHost { } const tr = this.findRow(e); - if (tr) { - const { index } = tr; + if (tr) { + const { index, pin } = tr; - if (highlight.row.canExecute(index)) { + let correctedIndex = index; + if (highlight.row.canExecute(correctedIndex)) { rows .filter(i => i !== index) .forEach(i => highlight.row.execute(i, false)); - highlight.row.execute(index, true); + if (pin === 'body') { + correctedIndex += model.row().pinTop.length; + } + if (pin === 'bottom') { + correctedIndex += model.row().pinTop.length + model.scene().rows.length; + } + highlight.row.execute(correctedIndex, true); } } @@ -344,7 +351,7 @@ export class ViewHost { const { table } = this.plugin; const pathFinder = new PathService(table.box.bag.body); const path = eventPath(e); - return pathFinder.row(path); + return pathFinder.row(path); } clearHighlight() { diff --git a/packages/qgrid-ngx/src/lib/body/body-core.component.html b/packages/qgrid-ngx/src/lib/body/body-core.component.html index 81385c116..91b74bcc6 100644 --- a/packages/qgrid-ngx/src/lib/body/body-core.component.html +++ b/packages/qgrid-ngx/src/lib/body/body-core.component.html @@ -38,11 +38,12 @@ + q-grid-core-source="body" + [q-grid-core-pin]="pin"> - diff --git a/packages/qgrid-ngx/src/lib/body/td-core.directive.ts b/packages/qgrid-ngx/src/lib/body/td-core.directive.ts index 5aa62dc88..624c40b57 100644 --- a/packages/qgrid-ngx/src/lib/body/td-core.directive.ts +++ b/packages/qgrid-ngx/src/lib/body/td-core.directive.ts @@ -23,9 +23,13 @@ export class TdCoreDirective implements DomTd, OnInit, OnDestroy, OnChanges { @Input('q-grid-core-td') columnView: ColumnView; + @Input('q-grid-core-pin') pin: string; + element: HTMLElement; changes: SimpleChange; + model; + constructor( public $view: GridLet, private root: GridRoot, @@ -40,7 +44,10 @@ export class TdCoreDirective implements DomTd, OnInit, OnDestroy, OnChanges { } ngOnInit() { - const { table } = this.root; + const { table, model } = this.root; + + this.model = model; + table.box.bag.body.addCell(this); this.cellClass.toBody(this.element, this.column); @@ -132,7 +139,14 @@ export class TdCoreDirective implements DomTd, OnInit, OnDestroy, OnChanges { } get rowIndex() { - return this.tr.index; + let index = this.tr.index; + if (this.pin == 'body') { + index += this.model.row().pinTop.length; + } + if (this.pin == 'bottom') { + index += this.model.row().pinTop.length + this.model.scene().rows.length; + } + return index; } get dataRowIndex() { diff --git a/packages/qgrid-ngx/src/lib/cell-handler/cell-handler.component.ts b/packages/qgrid-ngx/src/lib/cell-handler/cell-handler.component.ts index 1d20f2bed..04ebfd3fe 100644 --- a/packages/qgrid-ngx/src/lib/cell-handler/cell-handler.component.ts +++ b/packages/qgrid-ngx/src/lib/cell-handler/cell-handler.component.ts @@ -1,5 +1,6 @@ import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { CellView, EditService, Fastdom, jobLine, NavigationState, RowDetails } from '@qgrid/core'; +import { CellView, EditService, Fastdom, jobLine, NavigationState, RowDetails, Td } from '@qgrid/core'; +import { TdCoreDirective } from '../body/td-core.directive'; import { GridEventArg } from '../grid/grid-model'; import { GridPlugin } from '../plugin/grid-plugin'; @@ -107,7 +108,9 @@ export class CellHandlerComponent implements OnInit, AfterViewInit { const headHeight = table.view.height('head-mid'); - const top = Math.max(headHeight, (target.offsetTop - scrollState.top)); + const top = Math.max(headHeight, (target.offsetTop - + (!table.box.bag.body.findModel(target) || (table.box.bag.body.findModel(target) as TdCoreDirective).pin == 'body' ? scrollState.top : 0))); + const left = (target.offsetLeft - (cell.column.pin === 'mid' ? scrollState.left : 0)); const width = target.offsetWidth; const height = target.offsetHeight; diff --git a/packages/qgrid-ngx/src/lib/row/tr-core.directive.ts b/packages/qgrid-ngx/src/lib/row/tr-core.directive.ts index 5cf13f411..e0da7bd58 100644 --- a/packages/qgrid-ngx/src/lib/row/tr-core.directive.ts +++ b/packages/qgrid-ngx/src/lib/row/tr-core.directive.ts @@ -11,6 +11,8 @@ export class TrCoreDirective implements DomTr, OnInit, OnDestroy { @Input('q-grid-core-tr') model: any; @Input('q-grid-core-source') source; + @Input('q-grid-core-pin') pin: string; + element: HTMLElement; constructor( From 57964ecc93d7746e86511250e0d95260a738f284 Mon Sep 17 00:00:00 2001 From: Yuriy K Date: Fri, 8 Apr 2022 20:39:28 +0300 Subject: [PATCH 3/7] pinned rows: fix for scrolling and cell navigating --- .../qgrid-core/src/dom/selector/selector.mark.js | 3 ++- packages/qgrid-core/src/dom/view.js | 15 ++++++++++++--- .../qgrid-core/src/navigation/navigation.let.js | 4 ---- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/packages/qgrid-core/src/dom/selector/selector.mark.js b/packages/qgrid-core/src/dom/selector/selector.mark.js index 356110ccf..76ec10eb5 100644 --- a/packages/qgrid-core/src/dom/selector/selector.mark.js +++ b/packages/qgrid-core/src/dom/selector/selector.mark.js @@ -38,7 +38,8 @@ export class SelectorMark { const name = this.name + ((pinTB && pinTB !== 'mid') ? `-${pinTB}` : '') + (pinLR ? `-${pinLR}` : ''); const element = this.markup[name]; if (element) { - const prev = pinLR === 'left' ? null : result[result.length - 1]; + const prev = result[result.length - 1] && result[result.length - 1].name === (this.name + ((pinTB == 'top' || pinTB == 'bottom') ? `-${pinTB}` : '')) ? + result[result.length - 1] : null; const columnStart = prev ? prev.columnRange.end : 0; const columnCount = columnArea[pinLR].length; const rowStart = pinTB === 'mid' ? model.row().pinTop.length : pinTB === 'bottom' ? diff --git a/packages/qgrid-core/src/dom/view.js b/packages/qgrid-core/src/dom/view.js index ad0adb93c..f7ff6246a 100644 --- a/packages/qgrid-core/src/dom/view.js +++ b/packages/qgrid-core/src/dom/view.js @@ -108,12 +108,12 @@ export class View extends Unit { bodyMid.scrollLeft = value; } - const bodyTop = markup['body-top']; + const bodyTop = markup['body-top-mid']; if (bodyTop) { bodyTop.scrollLeft = value; } - const bodyBottom = markup['body-bottom']; + const bodyBottom = markup['body-bottom-mid']; if (bodyBottom) { bodyBottom.scrollLeft = value; } @@ -158,7 +158,16 @@ export class View extends Unit { break; } case 'top': { - return true; + target = target.element; + if (target) { + const { markup } = this.context; + const bodyLeft = markup['body-left']; + const bodyMid = markup['body-mid']; + const bodyRight = markup['body-right']; + return (bodyLeft && isParentOf(bodyLeft, target)) || + (bodyMid && isParentOf(bodyMid, target)) || + (bodyRight && isParentOf(bodyRight, target)); + } } } } diff --git a/packages/qgrid-core/src/navigation/navigation.let.js b/packages/qgrid-core/src/navigation/navigation.let.js index fa6490a4e..ded5b7563 100644 --- a/packages/qgrid-core/src/navigation/navigation.let.js +++ b/packages/qgrid-core/src/navigation/navigation.let.js @@ -173,10 +173,6 @@ export class NavigationLet { Fastdom.measure(() => { const tr = target.rect(); - //move this code - if (table.body.cell(target.rowIndex, target.columnIndex).model().td.pin !== 'body') { - return; - } const vr = view.rect('body-mid'); const state = {}; From 115e40507843684603ddf92b875052f77de9cc1b Mon Sep 17 00:00:00 2001 From: Yuriy K Date: Tue, 12 Apr 2022 17:20:03 +0300 Subject: [PATCH 4/7] pinned rows - fixes --- packages/qgrid-core/public-api.d.ts | 1 + .../src/dom/selector/selector.mark.js | 17 +---------------- .../src/navigation/navigation.let.js | 4 +++- packages/qgrid-core/src/row/row.model.d.ts | 8 ++++++++ .../qgrid-core/src/scene/view/cell.view.d.ts | 1 + .../qgrid-core/src/selection/selection.let.js | 6 ++++-- packages/qgrid-core/src/view/view.host.js | 2 +- .../templates/plugin-pager-target.tpl.html | 3 ++- .../src/lib/body/body-core.component.html | 5 ++--- .../src/lib/body/body-core.component.ts | 12 ++++++++---- .../src/lib/body/body-core.service.ts | 7 +++++++ .../src/lib/body/td-core.directive.ts | 19 ++++++++++--------- .../cell-handler/cell-handler.component.ts | 4 +--- .../src/lib/row/tr-core.directive.ts | 5 ++++- packages/qgrid-ngx/src/public-api.ts | 1 + 15 files changed, 54 insertions(+), 41 deletions(-) create mode 100644 packages/qgrid-core/src/row/row.model.d.ts create mode 100644 packages/qgrid-ngx/src/lib/body/body-core.service.ts diff --git a/packages/qgrid-core/public-api.d.ts b/packages/qgrid-core/public-api.d.ts index 50070ae7b..c628067a9 100644 --- a/packages/qgrid-core/public-api.d.ts +++ b/packages/qgrid-core/public-api.d.ts @@ -24,6 +24,7 @@ export { BoolColumn, BoolColumnModel } from './src/column-type/bool.column'; export { CohortColumn, CohortColumnModel } from './src/column-type/cohort.column'; //column-type export { ColumnModel, ColumnModelCategory, ColumnModelPin, ColumnModelType, ColumnModelWidthMode } from './src/column-type/column.model'; +export { RowModelPin } from './src/row/row.model'; export { CurrencyColumn, CurrencyColumnModel } from './src/column-type/currency.column'; export { DataColumnModel } from './src/column-type/data.column.model'; export { DateColumn, DateColumnModel } from './src/column-type/date.column'; diff --git a/packages/qgrid-core/src/dom/selector/selector.mark.js b/packages/qgrid-core/src/dom/selector/selector.mark.js index 76ec10eb5..dde7c4fca 100644 --- a/packages/qgrid-core/src/dom/selector/selector.mark.js +++ b/packages/qgrid-core/src/dom/selector/selector.mark.js @@ -10,22 +10,7 @@ export class SelectorMark { select() { const result = []; const addNext = this.addFactory(result); - if (this.name == 'body') { - addNext('left','top'); - addNext('mid','top'); - addNext('right','top'); - addNext('left','mid'); - addNext('mid','mid'); - addNext('right','mid'); - addNext('left','bottom'); - addNext('mid','bottom'); - addNext('right','bottom'); - } - else { - addNext('left', null); - addNext('mid', null); - addNext('right', null); - } + ['top', 'mid', 'bottom'].forEach(pos => (['left', 'mid', 'right'].forEach(pin => addNext(pin, pos)))); return result; } diff --git a/packages/qgrid-core/src/navigation/navigation.let.js b/packages/qgrid-core/src/navigation/navigation.let.js index ded5b7563..e7baceaac 100644 --- a/packages/qgrid-core/src/navigation/navigation.let.js +++ b/packages/qgrid-core/src/navigation/navigation.let.js @@ -30,12 +30,14 @@ export class NavigationLet { const td = table.body.cell(rowIndex, columnIndex).model(); if (td) { const { row, column } = td; + const rowPin = td.td.pin; model.navigation({ cell: { rowIndex, columnIndex, row, - column + column, + rowPin } }, { source: 'navigation.view', diff --git a/packages/qgrid-core/src/row/row.model.d.ts b/packages/qgrid-core/src/row/row.model.d.ts new file mode 100644 index 000000000..d2cfe3ed8 --- /dev/null +++ b/packages/qgrid-core/src/row/row.model.d.ts @@ -0,0 +1,8 @@ +/** + * Indicates if row should be frozen. + * - `'top'` - freeze a row on the grid's top. + * - `'body'` - do not freeze + * - `'bottom'` - freeze a row on the grid's bottom. + */ +export declare type RowModelPin = 'top' | 'body' | 'bottom'; + diff --git a/packages/qgrid-core/src/scene/view/cell.view.d.ts b/packages/qgrid-core/src/scene/view/cell.view.d.ts index 813e5f79e..3e1ab7d88 100644 --- a/packages/qgrid-core/src/scene/view/cell.view.d.ts +++ b/packages/qgrid-core/src/scene/view/cell.view.d.ts @@ -8,4 +8,5 @@ export interface CellViewPosition { export interface CellView extends CellViewPosition { readonly row: any; readonly column: ColumnModel; + readonly rowPin: string; } diff --git a/packages/qgrid-core/src/selection/selection.let.js b/packages/qgrid-core/src/selection/selection.let.js index bc5f198c2..412afad2e 100644 --- a/packages/qgrid-core/src/selection/selection.let.js +++ b/packages/qgrid-core/src/selection/selection.let.js @@ -427,13 +427,15 @@ export class SelectionLet { navigateTo(rowIndex, columnIndex) { const { table, model } = this.plugin; - const { row, column } = table.body.cell(rowIndex, columnIndex).model(); + const { row, column, td } = table.body.cell(rowIndex, columnIndex).model(); + const rowPin = td.pin; model.navigation({ cell: { rowIndex, columnIndex, row, - column + column, + rowPin } }, { source: 'selection.view' }); } diff --git a/packages/qgrid-core/src/view/view.host.js b/packages/qgrid-core/src/view/view.host.js index 397da4d02..9b849b204 100644 --- a/packages/qgrid-core/src/view/view.host.js +++ b/packages/qgrid-core/src/view/view.host.js @@ -351,7 +351,7 @@ export class ViewHost { const { table } = this.plugin; const pathFinder = new PathService(table.box.bag.body); const path = eventPath(e); - return pathFinder.row(path); + return pathFinder.row(path); } clearHighlight() { diff --git a/packages/qgrid-ngx-theme-material/src/lib/templates/plugin-pager-target.tpl.html b/packages/qgrid-ngx-theme-material/src/lib/templates/plugin-pager-target.tpl.html index 1f269cd89..7eaeec1f3 100644 --- a/packages/qgrid-ngx-theme-material/src/lib/templates/plugin-pager-target.tpl.html +++ b/packages/qgrid-ngx-theme-material/src/lib/templates/plugin-pager-target.tpl.html @@ -3,7 +3,8 @@ - + + q-grid-core-source="body"> - diff --git a/packages/qgrid-ngx/src/lib/body/body-core.component.ts b/packages/qgrid-ngx/src/lib/body/body-core.component.ts index fb29b670a..9fc8d0cf5 100644 --- a/packages/qgrid-ngx/src/lib/body/body-core.component.ts +++ b/packages/qgrid-ngx/src/lib/body/body-core.component.ts @@ -1,22 +1,24 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, Input, NgZone, OnInit } from '@angular/core'; -import { BodyHost, ColumnView, EventListener, EventManager, SelectionState } from '@qgrid/core'; +import { BodyHost, ColumnView, EventListener, EventManager, RowModelPin, SelectionState } from '@qgrid/core'; import { GridLet } from '../grid/grid-let'; import { GridModel } from '../grid/grid-model'; import { GridPlugin } from '../plugin/grid-plugin'; import { TableCoreService } from '../table/table-core.service'; -@Component({ +import { BodyCoreService } from './body-core.service'; +@Component({ // tslint:disable-next-line selector: 'tbody[q-grid-core-body]', templateUrl: './body-core.component.html', - providers: [GridPlugin], + providers: [GridPlugin, BodyCoreService], changeDetection: ChangeDetectionStrategy.OnPush }) export class BodyCoreComponent implements OnInit { - @Input() pin = 'body'; + @Input() pin: RowModelPin = 'body'; constructor( public $view: GridLet, public $table: TableCoreService, + public $body: BodyCoreService, private elementRef: ElementRef, private zone: NgZone, private cd: ChangeDetectorRef, @@ -30,6 +32,8 @@ export class BodyCoreComponent implements OnInit { const host = new BodyHost(this.plugin); + this.$body.pin = this.pin; + const listener = new EventListener(this.elementRef.nativeElement, new EventManager(this)); this.zone.runOutsideAngular(() => { const scrollSettings = { passive: true }; diff --git a/packages/qgrid-ngx/src/lib/body/body-core.service.ts b/packages/qgrid-ngx/src/lib/body/body-core.service.ts new file mode 100644 index 000000000..e5d77f5f1 --- /dev/null +++ b/packages/qgrid-ngx/src/lib/body/body-core.service.ts @@ -0,0 +1,7 @@ +import { Injectable } from '@angular/core'; +import { RowModelPin } from '@qgrid/core'; + +@Injectable() +export class BodyCoreService { + pin: RowModelPin; +} \ No newline at end of file diff --git a/packages/qgrid-ngx/src/lib/body/td-core.directive.ts b/packages/qgrid-ngx/src/lib/body/td-core.directive.ts index 624c40b57..105ccb436 100644 --- a/packages/qgrid-ngx/src/lib/body/td-core.directive.ts +++ b/packages/qgrid-ngx/src/lib/body/td-core.directive.ts @@ -11,6 +11,7 @@ import { DomTd } from '../dom/dom'; import { GridLet } from '../grid/grid-let'; import { GridRoot } from '../grid/grid-root'; import { TrCoreDirective } from '../row/tr-core.directive'; +import { BodyCoreService } from './body-core.service'; @Directive({ selector: '[q-grid-core-td]', @@ -22,31 +23,31 @@ export class TdCoreDirective implements DomTd, OnInit, OnDestroy, OnChanges { @Input('q-grid-core-label') actualLabel: any; @Input('q-grid-core-td') columnView: ColumnView; - - @Input('q-grid-core-pin') pin: string; + + pin: string; element: HTMLElement; changes: SimpleChange; - model; - constructor( public $view: GridLet, private root: GridRoot, private viewContainerRef: ViewContainerRef, private cellTemplate: CellTemplateService, private cellClass: CellClassService, + private $body: BodyCoreService, private tr: TrCoreDirective, private cd: ChangeDetectorRef, elementRef: ElementRef ) { this.element = elementRef.nativeElement.parentNode; + this.pin = $body.pin; } ngOnInit() { - const { table, model } = this.root; - - this.model = model; + const { table } = this.root; + + this.pin = this.$body.pin; table.box.bag.body.addCell(this); @@ -141,10 +142,10 @@ export class TdCoreDirective implements DomTd, OnInit, OnDestroy, OnChanges { get rowIndex() { let index = this.tr.index; if (this.pin == 'body') { - index += this.model.row().pinTop.length; + index += this.root.model.row().pinTop.length; } if (this.pin == 'bottom') { - index += this.model.row().pinTop.length + this.model.scene().rows.length; + index += this.root.model.row().pinTop.length + this.root.model.scene().rows.length; } return index; } diff --git a/packages/qgrid-ngx/src/lib/cell-handler/cell-handler.component.ts b/packages/qgrid-ngx/src/lib/cell-handler/cell-handler.component.ts index 04ebfd3fe..5220dc0c1 100644 --- a/packages/qgrid-ngx/src/lib/cell-handler/cell-handler.component.ts +++ b/packages/qgrid-ngx/src/lib/cell-handler/cell-handler.component.ts @@ -108,9 +108,7 @@ export class CellHandlerComponent implements OnInit, AfterViewInit { const headHeight = table.view.height('head-mid'); - const top = Math.max(headHeight, (target.offsetTop - - (!table.box.bag.body.findModel(target) || (table.box.bag.body.findModel(target) as TdCoreDirective).pin == 'body' ? scrollState.top : 0))); - + const top = Math.max(headHeight, target.offsetTop - (cell.rowPin === "body" ? scrollState.top : 0)); const left = (target.offsetLeft - (cell.column.pin === 'mid' ? scrollState.left : 0)); const width = target.offsetWidth; const height = target.offsetHeight; diff --git a/packages/qgrid-ngx/src/lib/row/tr-core.directive.ts b/packages/qgrid-ngx/src/lib/row/tr-core.directive.ts index e0da7bd58..b236eb04a 100644 --- a/packages/qgrid-ngx/src/lib/row/tr-core.directive.ts +++ b/packages/qgrid-ngx/src/lib/row/tr-core.directive.ts @@ -1,4 +1,5 @@ import { Directive, ElementRef, Input, OnDestroy, OnInit } from '@angular/core'; +import { BodyCoreService } from '../body/body-core.service'; import { DomTr } from '../dom/dom'; import { GridLet } from '../grid/grid-let'; import { GridPlugin } from '../plugin/grid-plugin'; @@ -11,16 +12,18 @@ export class TrCoreDirective implements DomTr, OnInit, OnDestroy { @Input('q-grid-core-tr') model: any; @Input('q-grid-core-source') source; - @Input('q-grid-core-pin') pin: string; + pin: string; element: HTMLElement; constructor( public $view: GridLet, + private $body: BodyCoreService, private plugin: GridPlugin, elementRef: ElementRef ) { this.element = elementRef.nativeElement; + this.pin = $body.pin; } get index() { diff --git a/packages/qgrid-ngx/src/public-api.ts b/packages/qgrid-ngx/src/public-api.ts index d8186dbad..fa30126cc 100644 --- a/packages/qgrid-ngx/src/public-api.ts +++ b/packages/qgrid-ngx/src/public-api.ts @@ -62,6 +62,7 @@ export { ScrollService } from './lib/scroll/scroll.service'; export { StateAccessor } from './lib/state/state-accessor'; export { TableCoreComponent } from './lib/table/table-core.component'; export { TableCoreService } from './lib/table/table-core.service'; +export { BodyCoreService } from './lib/body/body-core.service'; export { TableModule } from './lib/table/table.module'; export { TemplateCacheDirective } from './lib/template/template-cache.directive'; export { TemplateCacheService } from './lib/template/template-cache.service'; From fee7f2c831831cdb0ab59634a1d605f38ec73d41 Mon Sep 17 00:00:00 2001 From: Yuriy K Date: Thu, 14 Apr 2022 16:51:47 +0300 Subject: [PATCH 5/7] small fix --- packages/qgrid-core/src/navigation/navigation.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/qgrid-core/src/navigation/navigation.js b/packages/qgrid-core/src/navigation/navigation.js index 16efbb0c6..e770dd664 100644 --- a/packages/qgrid-core/src/navigation/navigation.js +++ b/packages/qgrid-core/src/navigation/navigation.js @@ -123,12 +123,14 @@ export class Navigation { const cell = this.table.body.cell(rowIndex, columnIndex); const model = cell.model(); if (model) { - const { row, column } = model; + const { row, column, td } = model; + const rowPin = td.pin; return { rowIndex, columnIndex, row, - column + column, + rowPin }; } From 2acb7cda62be9e4e096697310e1afba4a11771c8 Mon Sep 17 00:00:00 2001 From: Yuriy K Date: Thu, 14 Apr 2022 19:09:12 +0300 Subject: [PATCH 6/7] style and nav fixes in grid with pinned rows --- packages/qgrid-ngx/src/lib/body/body-core.component.ts | 2 +- packages/qgrid-styles/view.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/qgrid-ngx/src/lib/body/body-core.component.ts b/packages/qgrid-ngx/src/lib/body/body-core.component.ts index 9fc8d0cf5..6664bade9 100644 --- a/packages/qgrid-ngx/src/lib/body/body-core.component.ts +++ b/packages/qgrid-ngx/src/lib/body/body-core.component.ts @@ -41,7 +41,7 @@ export class BodyCoreComponent implements OnInit { listener.on('scroll', () => host.scroll({ scrollLeft: this.$table.pin === 'mid' ? nativeElement.scrollLeft : model.scroll().left, - scrollTop: nativeElement.scrollTop + scrollTop: this.$body.pin === 'body' ? nativeElement.scrollTop : model.scroll().top }), scrollSettings )); diff --git a/packages/qgrid-styles/view.scss b/packages/qgrid-styles/view.scss index d24795c40..be4eac1c2 100644 --- a/packages/qgrid-styles/view.scss +++ b/packages/qgrid-styles/view.scss @@ -41,7 +41,7 @@ .q-grid-with-bottom-pin { >.q-grid-view { - >.q-grid-table-mid { + >.q-grid-table-left, >.q-grid-table-mid, >.q-grid-table-right { >table { >tbody:not(.q-grid-body-bottom) { overflow-x: hidden; From ddc01900c5d4565a2ae1090dcbbc160760595bd2 Mon Sep 17 00:00:00 2001 From: Yuriy K Date: Wed, 20 Apr 2022 18:04:30 +0300 Subject: [PATCH 7/7] Pinned rows - added to scene --- packages/qgrid-core/src/cell/cell.selector.js | 2 +- .../qgrid-core/src/dom/selector/selector.mark.js | 12 +++++++++--- packages/qgrid-core/src/pipe/pagination.pipe.js | 2 +- packages/qgrid-core/src/scene/render/render.js | 12 ++++++++---- packages/qgrid-core/src/view/view.host.js | 15 +++------------ .../qgrid-ngx/src/lib/body/body-core.service.ts | 13 +++++++++++++ .../qgrid-ngx/src/lib/body/td-core.directive.ts | 9 +-------- .../qgrid-ngx/src/lib/row/tr-core.directive.ts | 2 +- 8 files changed, 37 insertions(+), 30 deletions(-) diff --git a/packages/qgrid-core/src/cell/cell.selector.js b/packages/qgrid-core/src/cell/cell.selector.js index 9e5e8a549..b0f5a00f6 100644 --- a/packages/qgrid-core/src/cell/cell.selector.js +++ b/packages/qgrid-core/src/cell/cell.selector.js @@ -53,7 +53,7 @@ export class CellSelector { mapFromCells(items) { const { model, table } = this; const result = []; - const rows = model.row().pinTop.concat(model.scene().rows).concat(model.row().pinBottom); + const rows = table.data.rows(); const columns = table.data.columns(); for (let item of items) { diff --git a/packages/qgrid-core/src/dom/selector/selector.mark.js b/packages/qgrid-core/src/dom/selector/selector.mark.js index dde7c4fca..ecfdb1948 100644 --- a/packages/qgrid-core/src/dom/selector/selector.mark.js +++ b/packages/qgrid-core/src/dom/selector/selector.mark.js @@ -19,7 +19,13 @@ export class SelectorMark { const columnArea = model.scene().column.area; return (pinLR, pinTB) => { - const rows = pinTB == 'top' ? model.row().pinTop : pinTB == 'bottom' ? model.row().pinBottom : model.scene().rows; + + const { pinTop, pinBottom } = model.row(); + const pinned = new Set([...pinTop, ...pinBottom]); + + const rows = pinTB == 'top' ? pinTop : pinTB == 'bottom' ? pinBottom : + (pinned.size ? model.scene().rows.filter(row => !pinned.has(row)) : model.scene().rows); + const name = this.name + ((pinTB && pinTB !== 'mid') ? `-${pinTB}` : '') + (pinLR ? `-${pinLR}` : ''); const element = this.markup[name]; if (element) { @@ -27,8 +33,8 @@ export class SelectorMark { result[result.length - 1] : null; const columnStart = prev ? prev.columnRange.end : 0; const columnCount = columnArea[pinLR].length; - const rowStart = pinTB === 'mid' ? model.row().pinTop.length : pinTB === 'bottom' ? - model.row().pinTop.length + model.scene().rows.length : 0; + const rowStart = pinTB === 'mid' ? pinTop.length : pinTB === 'bottom' ? + model.scene().rows.length - pinBottom.length : 0; const rowCount = rows.length; result.push({ diff --git a/packages/qgrid-core/src/pipe/pagination.pipe.js b/packages/qgrid-core/src/pipe/pagination.pipe.js index fabb437de..4bf64b5d8 100644 --- a/packages/qgrid-core/src/pipe/pagination.pipe.js +++ b/packages/qgrid-core/src/pipe/pagination.pipe.js @@ -43,6 +43,6 @@ function paginate(model, rows) { const start = current * size; model.pagination({ count, current }, { source: 'pagination.pipe', behavior: 'core' }); - return mode === 'virtual' ? rows : rows.slice(start, start + size); + return mode === 'virtual' ? rows : pinTop.concat(rows.slice(start, start + size)).concat(pinBottom); } diff --git a/packages/qgrid-core/src/scene/render/render.js b/packages/qgrid-core/src/scene/render/render.js index ca8acad06..1f1d03192 100644 --- a/packages/qgrid-core/src/scene/render/render.js +++ b/packages/qgrid-core/src/scene/render/render.js @@ -82,15 +82,19 @@ export class Renderer { }; this.rows = { - left: [], - right: [], - mid: [] + top: [], + body: [], + bottom: [] }; const invalidateRows = () => { - const { rows } = model.scene(); + let { rows } = model.scene(); const { pinTop, pinBottom } = model.row(); + const pinned = new Set([...pinTop, ...pinBottom]); + if (pinned.size) { + rows = rows.filter(row => !pinned.has(row)) + } this.rows = { top: pinTop, body: rows, diff --git a/packages/qgrid-core/src/view/view.host.js b/packages/qgrid-core/src/view/view.host.js index 9b849b204..b56cd2655 100644 --- a/packages/qgrid-core/src/view/view.host.js +++ b/packages/qgrid-core/src/view/view.host.js @@ -207,21 +207,12 @@ export class ViewHost { const tr = this.findRow(e); if (tr) { - const { index, pin } = tr; - - let correctedIndex = index; - if (highlight.row.canExecute(correctedIndex)) { + const { index } = tr; + if (highlight.row.canExecute(index)) { rows .filter(i => i !== index) .forEach(i => highlight.row.execute(i, false)); - - if (pin === 'body') { - correctedIndex += model.row().pinTop.length; - } - if (pin === 'bottom') { - correctedIndex += model.row().pinTop.length + model.scene().rows.length; - } - highlight.row.execute(correctedIndex, true); + highlight.row.execute(index, true); } } diff --git a/packages/qgrid-ngx/src/lib/body/body-core.service.ts b/packages/qgrid-ngx/src/lib/body/body-core.service.ts index e5d77f5f1..68792b430 100644 --- a/packages/qgrid-ngx/src/lib/body/body-core.service.ts +++ b/packages/qgrid-ngx/src/lib/body/body-core.service.ts @@ -1,7 +1,20 @@ import { Injectable } from '@angular/core'; import { RowModelPin } from '@qgrid/core'; +import { GridPlugin } from '../plugin/grid-plugin'; @Injectable() export class BodyCoreService { + + constructor(private plugin: GridPlugin) { + } + pin: RowModelPin; + + get offsetIndex() { + switch (this.pin) { + case "body": return this.plugin.model.row().pinTop.length; + case "bottom": return this.plugin.model.scene().rows.length - this.plugin.model.row().pinBottom.length; + default: return 0; + } + } } \ No newline at end of file diff --git a/packages/qgrid-ngx/src/lib/body/td-core.directive.ts b/packages/qgrid-ngx/src/lib/body/td-core.directive.ts index 105ccb436..de6c92f16 100644 --- a/packages/qgrid-ngx/src/lib/body/td-core.directive.ts +++ b/packages/qgrid-ngx/src/lib/body/td-core.directive.ts @@ -140,14 +140,7 @@ export class TdCoreDirective implements DomTd, OnInit, OnDestroy, OnChanges { } get rowIndex() { - let index = this.tr.index; - if (this.pin == 'body') { - index += this.root.model.row().pinTop.length; - } - if (this.pin == 'bottom') { - index += this.root.model.row().pinTop.length + this.root.model.scene().rows.length; - } - return index; + return this.tr.index; } get dataRowIndex() { diff --git a/packages/qgrid-ngx/src/lib/row/tr-core.directive.ts b/packages/qgrid-ngx/src/lib/row/tr-core.directive.ts index b236eb04a..af20958ca 100644 --- a/packages/qgrid-ngx/src/lib/row/tr-core.directive.ts +++ b/packages/qgrid-ngx/src/lib/row/tr-core.directive.ts @@ -27,7 +27,7 @@ export class TrCoreDirective implements DomTr, OnInit, OnDestroy { } get index() { - return this.$view.scroll.y.container.position + this.viewIndex; + return this.$view.scroll.y.container.position + this.viewIndex + this.$body.offsetIndex; } ngOnInit() {