Skip to content

Commit

Permalink
fix(datagrid): virtual scroll load extra page for details (#1431)
Browse files Browse the repository at this point in the history
## PR Checklist

Please check if your PR fulfills the following requirements:

- [ ] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)
- [ ] If applicable, have a visual design approval

## PR Type

What kind of change does this PR introduce?

<!-- Please check the one that applies to this PR using "x". -->

- [x] Bugfix
- [ ] Feature
- [ ] Code style update (formatting, local variables)
- [ ] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] CI related changes
- [ ] Documentation content changes
- [ ] Other... Please describe:

## What is the current behavior?
Virtual scroller load extra page when close detail page.

<!-- Please describe the current behavior that you are modifying, or
link to a relevant issue. -->

Issue Number: CDE-2070

## What is the new behavior?
Virtual scroller don't load extra page when close detail page.

## Does this PR introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this PR contains a breaking change, please describe the impact
and migration path for existing applications below. -->

## Other information
  • Loading branch information
valentin-mladenov authored Jun 12, 2024
1 parent 76b13f8 commit f402878
Show file tree
Hide file tree
Showing 10 changed files with 54 additions and 17 deletions.
10 changes: 8 additions & 2 deletions projects/angular/clarity.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1446,7 +1446,9 @@ export interface ClrDatagridComparatorInterface<T> {

// @public (undocumented)
export class ClrDatagridDetail {
constructor(detailService: DetailService, commonStrings: ClrCommonStringsService);
constructor(detailService: DetailService, commonStrings: ClrCommonStringsService, cdr: ChangeDetectorRef);
// (undocumented)
cdr: ChangeDetectorRef;
// (undocumented)
close(): void;
// (undocumented)
Expand All @@ -1470,13 +1472,17 @@ export class ClrDatagridDetailBody {
}

// @public (undocumented)
export class ClrDatagridDetailHeader {
export class ClrDatagridDetailHeader implements AfterViewInit {
constructor(detailService: DetailService, commonStrings: ClrCommonStringsService);
// (undocumented)
commonStrings: ClrCommonStringsService;
// (undocumented)
detailService: DetailService;
// (undocumented)
ngAfterViewInit(): void;
// (undocumented)
title: ElementRef;
// (undocumented)
get titleId(): string;
// (undocumented)
static ɵcmp: i0.ɵɵComponentDeclaration<ClrDatagridDetailHeader, "clr-dg-detail-header", never, {}, {}, never, ["*"], false, never>;
Expand Down
12 changes: 9 additions & 3 deletions projects/angular/src/data/datagrid/datagrid-detail-header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* The full license information can be found in LICENSE in the root directory of this project.
*/

import { Component } from '@angular/core';
import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core';

import { ClrCommonStringsService } from '../../utils/i18n/common-strings.service';
import { DetailService } from './providers/detail.service';
Expand All @@ -16,7 +16,7 @@ import { DetailService } from './providers/detail.service';
'[class.datagrid-detail-header]': 'true',
},
template: `
<div class="datagrid-detail-header-title" cdkFocusInitial tabindex="-1" [id]="titleId">
<div #title class="datagrid-detail-header-title" tabindex="-1" [id]="titleId">
<ng-content></ng-content>
</div>
<div class="datagrid-detail-pane-close">
Expand All @@ -31,10 +31,16 @@ import { DetailService } from './providers/detail.service';
</div>
`,
})
export class ClrDatagridDetailHeader {
export class ClrDatagridDetailHeader implements AfterViewInit {
@ViewChild('title') title: ElementRef;

constructor(public detailService: DetailService, public commonStrings: ClrCommonStringsService) {}

get titleId() {
return `${this.detailService.id}-title`;
}

ngAfterViewInit(): void {
this.title.nativeElement.focus();
}
}
10 changes: 7 additions & 3 deletions projects/angular/src/data/datagrid/datagrid-detail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* The full license information can be found in LICENSE in the root directory of this project.
*/

import { Component, ContentChild } from '@angular/core';
import { ChangeDetectorRef, Component, ContentChild } from '@angular/core';

import { ClrCommonStringsService } from '../../utils/i18n/common-strings.service';
import { ClrDatagridDetailHeader } from './datagrid-detail-header';
Expand All @@ -21,7 +21,7 @@ import { DetailService } from './providers/detail.service';
template: `
<div
cdkTrapFocus
[cdkTrapFocusAutoCapture]="true"
[cdkTrapFocusAutoCapture]="!header"
class="datagrid-detail-pane-content"
*ngIf="detailService.isOpen"
role="dialog"
Expand All @@ -38,7 +38,11 @@ import { DetailService } from './providers/detail.service';
export class ClrDatagridDetail {
@ContentChild(ClrDatagridDetailHeader) header: ClrDatagridDetailHeader;

constructor(public detailService: DetailService, public commonStrings: ClrCommonStringsService) {}
constructor(
public detailService: DetailService,
public commonStrings: ClrCommonStringsService,
public cdr: ChangeDetectorRef
) {}

close(): void {
this.detailService.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export class ClrDatagridVirtualScrollDirective<T> implements AfterViewInit, DoCh
) {
this.items.smartenUp();
this.datagrid.hasVirtualScroller = true;
this.datagrid.detailService.preventFocusScroll = true;

this.datagridElementRef = this.datagrid.el;

Expand Down
2 changes: 1 addition & 1 deletion projects/angular/src/data/datagrid/datagrid.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ class TabsIntegrationTest {

@Component({
template: `
<clr-datagrid [clrDgItemsTrackBy]="trackBy">
<clr-datagrid [clrDgItemsTrackBy]="trackById">
<clr-dg-column>Item</clr-dg-column>
<clr-dg-row *ngFor="let item of items" [clrDgItem]="item">
<clr-dg-cell>{{ item.id }}</clr-dg-cell>
Expand Down
7 changes: 5 additions & 2 deletions projects/angular/src/data/datagrid/datagrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,13 +280,16 @@ export class ClrDatagrid<T = any> implements AfterContentInit, AfterViewInit, On
*/
if (row) {
this.detailService.open(row.item, row.detailButton.nativeElement);
} else if (!this.hasVirtualScroller || !row) {
}
// always keep open when virtual scroll is available otherwise close it
else if (!this.hasVirtualScroller) {
this.detailService.close();
}
}

// retain active cell when navigating with PageUp and PageDown buttons in virtual scroller
// retain active cell when navigating with Up/Down Arrows, PageUp and PageDown buttons in virtual scroller
const active = this.keyNavigation.getActiveCell();

if (active) {
this.zone.runOutsideAngular(() => {
setTimeout(() => this.keyNavigation.setActiveCell(active));
Expand Down
10 changes: 9 additions & 1 deletion projects/angular/src/data/datagrid/providers/detail.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { ModalStackService } from '../../../modal/modal-stack.service';
export class DetailService {
id: string;

private preventScroll = false;
private toggleState = false;
private cache: any;
private button: HTMLButtonElement;
Expand All @@ -29,6 +30,13 @@ export class DetailService {
this._enabled = state;
}

get preventFocusScroll(): boolean {
return this.preventScroll;
}
set preventFocusScroll(preventScroll: boolean) {
this.preventScroll = preventScroll;
}

get state() {
return this.cache;
}
Expand Down Expand Up @@ -58,7 +66,7 @@ export class DetailService {

returnFocus() {
if (this.button) {
this.button.focus();
this.button.focus({ preventScroll: this.preventFocusScroll });
this.button = null;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,12 @@ export class KeyNavigationGridController implements OnDestroy {
}

activeCell.setAttribute('tabindex', '0');
this._activeCell = activeCell;

const items = getTabableItems(activeCell);
const item = activeCell.getAttribute('role') !== 'columnheader' && items[0] ? items[0] : activeCell;

item.focus();
this._activeCell = item;
}

private getNextItemCoordinate(e: any) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,19 @@ <h3>Dynamic rows with sorting</h3>
ClrVirtualScroll
let-user
[clrVirtualRowsOf]="data.users"
[clrVirtualRowsItemSize]="24"
[clrVirtualRowsItemSize]="32"
[clrVirtualRowsMinBufferPx]="200"
[clrVirtualRowsMaxBufferPx]="400"
(renderedRangeChange)="renderRangeChange($event)"
>
<clr-dg-row [clrDgItem]="user">
<clr-dg-cell>{{user.id}}</clr-dg-cell>
<clr-dg-cell>{{user.name}}</clr-dg-cell>
<clr-dg-cell>
<clr-checkbox-wrapper>
<label>{{user.name}}</label>
<input type="checkbox" clrCheckbox />
</clr-checkbox-wrapper>
</clr-dg-cell>
<clr-dg-cell>{{user.creation | date}}</clr-dg-cell>
<clr-dg-cell>
{{user.pokemon.name}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { ListRange } from '@angular/cdk/collections';
import { ApplicationRef, ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { AfterViewChecked, ApplicationRef, ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { ClrDatagridSortOrder } from '@clr/angular';
import { BehaviorSubject, Observable } from 'rxjs';

Expand All @@ -26,7 +26,7 @@ class ChangeDetectionPerfRecord {
templateUrl: './virtual-scroll-client-side.html',
styleUrls: ['../datagrid.demo.scss'],
})
export class DatagridVirtualScrollClientSideDemo implements OnInit {
export class DatagridVirtualScrollClientSideDemo implements OnInit, AfterViewChecked {
totalRows = 10000;
totalCols = 5;
cols: Column[];
Expand Down Expand Up @@ -63,6 +63,10 @@ export class DatagridVirtualScrollClientSideDemo implements OnInit {
};
}

ngAfterViewChecked(): void {
this.cdr.detectChanges();
}

ngOnInit(): void {
this.calculateDatagrid();

Expand Down

0 comments on commit f402878

Please sign in to comment.