Search code examples
angularangular-material2angular-cdk

Cdk virtual-scroll inside mat-select for mat-option


Has anyone been able to use virtual-scroll inside mat-select as shown below ?

<mat-form-field>
    <mat-select placeholder="State">
        <cdk-virtual-scroll-viewport autosize>
            <mat-option *cdkVirtualFor="let state of states" [value]="state">{{state}}</mat-option>
        </cdk-virtual-scroll-viewport>
    </mat-select>
</mat-form-field>

As you can see https://stackblitz.com/edit/angular-h4xptu?file=app%2Fselect-reset-example.html it does not work - causes weird blank space as you scroll.


Solution

  • I think i have solved this:

    https://stackblitz.com/edit/angular-gs4scp

    The key things are when the mat select opens panel we trigger cdkVirtualScrollViewPort scroll and check view port size.

      openChange($event: boolean) {
        console.log("open change", $event);
        if ($event) {
          this.cdkVirtualScrollViewPort.scrollToIndex(0);
          this.cdkVirtualScrollViewPort.checkViewportSize();
        } else {
        }
      }
    

    Where we get the reference to the virtual scroll viewport using @ViewChild

    @ViewChild(CdkVirtualScrollViewport, { static: false })
      cdkVirtualScrollViewPort: CdkVirtualScrollViewport;
    

    Other relevant pieces in the template are are pretty simple:-

    <mat-form-field>
        <mat-select [formControl]="itemSelect"
      placeholder="Select Item"
      (openedChange)="openChange($event)">
        <mat-select-trigger>
          {{ itemTrigger }}
        </mat-select-trigger>
            <cdk-virtual-scroll-viewport itemSize="5" minBufferPx="200" maxBufferPx="400" class="example-viewport-select">
                <mat-option *cdkVirtualFor="let item of items" [value]="item"
                    (onSelectionChange)="onSelectionChange($event)">{{item}}</mat-option>
            </cdk-virtual-scroll-viewport>
        </mat-select>
        <mat-hint>Justa hint</mat-hint>
    </mat-form-field>