I’m implementing a multi-select dropdown using Angular Material’s <mat-select multiple> and cdk-virtual-scroll-viewport for performance with large datasets.
Problem:
When I select multiple branches, scroll down, and then select more branches, the earlier selected ones become unselected.
<mat-select multiple [(ngModel)]="selectedBranches" [compareWith]="compareBranches">
<mat-select-trigger>
<span *ngIf="selectedBranches.length === 0">Select branches...</span>
<span *ngIf="selectedBranches.length === 1">{{ selectedBranches[0].name }}</span>
<span *ngIf="selectedBranches.length > 1">{{ selectedBranches.length }} branches selected</span>
</mat-select-trigger>
<!-- Search input -->
<div class="search-container">
<mat-form-field appearance="outline" class="search-field">
<mat-label>Search branches</mat-label>
<input matInput [(ngModel)]="searchText" (ngModelChange)="onSearchChange()" />
<mat-icon matSuffix>search</mat-icon>
</mat-form-field>
</div>
<!-- Select All -->
<div style="margin-left: 17px; margin-bottom: 8px; margin-top: 8px;">
<mat-checkbox
[checked]="selectAllChecked"
[indeterminate]="isIndeterminate()"
(change)="toggleSelectAll($event)"
>
Select All
</mat-checkbox>
</div>
<!-- Virtual scroll -->
<cdk-virtual-scroll-viewport itemSize="48" class="branch-viewport">
<mat-option
*cdkVirtualFor="let branch of branchDropdownList; trackBy: trackByBranchId"
[value]="branch"
>
{{ branch.code }} - {{ branch.name }}
</mat-option>
</cdk-virtual-scroll-viewport>
</mat-select>
What I’ve Tried:
Implemented
[compareWith]comparingbranch.idto preserve selection.Verified
branchDropdownListcontains unique objects.Added
trackBywith*cdkVirtualFor.Ensured
branchDropdownListarray isn’t being reassigned unnecessarily.Tested without virtual scroll — selection works fine.
Expected Behavior:
Selections should persist regardless of scrolling or loading more options.
Actual Behavior:
With virtual scroll enabled, earlier selections disappear when scrolling and selecting new items.
What I’ve Tried Implemented [compareWith] function comparing branch.id to preserve selection.
Environment:
Angular 13.x
@angular/material 13.x
@angular/cdk 13.x
Tailwind CSS 3.x
How can I persist selected items in a Material multi-select that uses cdk-virtual-scroll-viewport, so selections are not lost after scrolling? Is there a recommended way to use [compareWith] or trackBy to prevent DOM recycling from breaking selection state?