2 years ago
#24346
borjaj
NG-ZORRO and Angular CDK infinite scroll is not working well
I'm using cdk virtual scrolling in an Angular project with Ng-zorro. I have a list of collapse component and in that list is where I use the virtual scrolling.
The problem is that when I open a collapse, if the content is bigger than the window heigth, when I scroll another collapse is open.
I supose that it occours because when the virtual scrolling load more content it gives an id for each collapse component which changes every time I make scrolling. But that it's a vague idea and I didn't found info about that.
This is my hmtl list file:
<div class="fair">
<h3>{{exhibition.toString()}}</h3>
</div>
<nz-radio-group class="radio-buttons" [(ngModel)]="userStats" [hidden]="!isAdmin && !isManager">
<label nz-radio-button [nzValue]="true" (click)="clickedMyVisits()">My Visits</label>
<label nz-radio-button [nzValue]="false" (click)="clickedAllVisits()">All Visits</label>
</nz-radio-group>
<cdk-virtual-scroll-viewport appendOnly itemSize="41">
<app-visit-info
*cdkVirtualFor="let visit of visitDataSource"
[visit]="visit"
[showUsername]="isAdmin || isManager"
[username]="this.username.toUpperCase()">
</app-visit-info>
</cdk-virtual-scroll-viewport>
<ng-template #loading>
<nz-spin nzTip="Loading..." class="spin"></nz-spin>
</ng-template>
<ng-template #empty>
<nz-empty class="empty"></nz-empty>
</ng-template>
This is my collapse component:
<nz-collapse>
<nz-collapse-panel [nzHeader]="showUsername ? visit.toPanelUserString() : visit.toPanelString()">
<div *ngIf="visit; else loading">
<div class="title">
<h2>{{visit.name}}</h2>
<h2 *ngIf="visit.visitType">{{visit.visitType?.description}}</h2>
<h2>{{visit.systemDate | date: "dd/MM/yyyy HH:mm"}}</h2>
</div>
</div>
</nz-collapse-panel>
</nz-collapse>
This is my ts file:
@Component({
selector: 'app-visit-list',
templateUrl: './visit-list.component.html',
styleUrls: ['./visit-list.component.less'],
})
export class VisitListComponent implements OnInit, OnDestroy {
visits$!: Observable<Visit[]>;
user$!: Observable<User>;
companyCode!: string;
username!: string;
exhibitionCode!: string;
exhibition!: Exhibition;
userStats = true;
visitQuery: VisitQuery = {};
visitDataSource!: VisitDataSource;
isAdmin!: boolean;
isManager!: boolean;
subscriptions$: Subscription[] = [];
constructor(private visitService: VisitService,
private activatedRoute: ActivatedRoute,
private authService: AuthService,
private store: Store) {
this.visitDataSource = new VisitDataSource(this.visitService, this.visitQuery, this.companyCode);
}
ngOnDestroy(): void {
this.subscriptions$.forEach(sub => sub.unsubscribe());
}
ngOnInit(): void {
this.subscriptions$.push(this.store.select(state => state.companyCode.companyCode).subscribe(
companyCode => {
this.companyCode = companyCode;
this.loadData();
}
));
}
loadData(){
this.username = this.activatedRoute.snapshot.paramMap.get('username')!;
this.companyCode = this.activatedRoute.snapshot.paramMap.get('companyCode')!;
this.exhibitionCode = this.activatedRoute.snapshot.paramMap.get('exhibitionCode')!;
this.exhibition = GlobalExhibition.exhibition;
this.isAdmin = this.authService.hasAdminRole();
this.isManager = this.authService.hasManagernRole();
this.visitQuery = {
username: this.username,
exhibitionCode: this.exhibitionCode,
visitUsername: this.username
}
this.clickedMyVisits();
}
clickedAllVisits() {
this.visitQuery = {
username: this.username,
exhibitionCode: this.exhibitionCode,
}
this.visitDataSource = new VisitDataSource(this.visitService, this.visitQuery, this.companyCode);
}
clickedMyVisits() {
this.visitQuery = {
username: this.username,
exhibitionCode: this.exhibitionCode,
visitUsername: this.username
}
this.visitDataSource = new VisitDataSource(this.visitService, this.visitQuery, this.companyCode);
}
}
class VisitDataSource extends DataSource<Visit> {
public itemsInMemory = Array.from<Visit>({length: 0});
private itemChanges$: BehaviorSubject<Visit[]> = new BehaviorSubject<Visit[]>([]);
private destroy$: Subject<boolean> = new Subject();
private pageSize = 25;
private lastLoadedPage = 0;
constructor(private visitService: VisitService,
private visitQuery: VisitQuery,
private companyCode: string){
super();
visitQuery.pageSize = this.pageSize;
this.itemChanges$ = new BehaviorSubject(this.itemsInMemory);
this.getInformation();
}
connect(collectionViewer: CollectionViewer){
collectionViewer.viewChange.pipe(takeUntil(this.destroy$)).subscribe(range => {
const currentPage = Math.floor(range.end / this.pageSize);
if(currentPage > this.lastLoadedPage){
this.lastLoadedPage = currentPage;
this.getInformation();
}
});
return this.itemChanges$;
}
getInformation(){
this.visitQuery.offset = this.lastLoadedPage * this.pageSize;
this.visitQuery.companyCode = this.companyCode;
if(this.visitQuery.exhibitionCode){
this.visitService.findVisitsPagination(this.visitQuery).subscribe(data =>{
data.forEach(visit => {
this.itemsInMemory.push(visit);
this.itemChanges$.next(this.itemsInMemory);
})
});
}
}
disconnect(){
this.destroy$.next(true);
this.destroy$.complete();
}
}
Thank you everyone! <3
html
angular
angular-cdk
ng-zorro-antd
angular-cdk-virtual-scroll
0 Answers
Your Answer