Search code examples
angularangular-material-table

Access a specific row in a Material Table in Angular


I have the following html

<mat-card>
  <mat-card-header>
    <mat-card-title>Results</mat-card-title>
  </mat-card-header>
  <mat-card-content [style.overflow]="'auto'">
    <table mat-table [dataSource]="[resultEntries$()][0]">
      <ng-container matColumnDef="col-lemma">
        <td mat-cell *matCellDef="let element">
          <!-- [...] -->
        </td>
      </ng-container>
      <!-- [...] -->
      <tr
        mat-row
        #tableRows
        *matRowDef="let row; columns: displayedColumns; let index = index"
        (click)="cindex = index"
        [class.selected]="index == cindex"
      ></tr>
    </table>
  </mat-card-content>
</mat-card>

And I need to scroll into a specific row stored in variable called myIndex, and I'm trying the following code:

  @ViewChildren('tableRows', { read: ElementRef })
  rowContainers: QueryList<ElementRef<HTMLTableRowElement>> = new QueryList<
    ElementRef<HTMLTableRowElement>
  >();

  constructor() {
    effect(() => {
      setTimeout(() => {
        this.rowContainers.first.nativeElement.scrollIntoView({
          behavior: 'instant',
        });
      });
    });
  }

If I console.log(this.rowContainers.first.nativeElement), I don't even get a list of rows from the dataSource.

<tr _ngcontent-ng-c2872871574 role="row" mat-row class="mat-mdc-row mdc-data-table__row cdk-row selected ng-star-inserted"></tr>

I don't know how to scroll to the nth element of the dataSource, where "n" is an integer stored in myIndex, and myIndex is known even before the dataSource loads. Any help will be appreciated. Thank you.


Solution

  • Convert your list of rows to array and take it from there. Here is a simple example that works (with a hard-coded list of rows, arbitrarily scrolls item no. 44 into view):

    Template

    <button (click)="scroll()">Scroll</button>
    <table mat-table [dataSource]="list">
      <ng-container matColumnDef="n">
        <td mat-cell *matCellDef="let element">
          {{ element.n }}
        </td>
      </ng-container>
      <tr mat-row *matRowDef="let row; columns: displayedColumns;" #tableRow></tr>
    </table>
    

    Class

    export class App {
      list = [] as { n: number }[];
      displayedColumns = ['n'];
      @ViewChildren('tableRow', { read: ElementRef }) rows = [] as ElementRef<HTMLTableRowElement>[];
    
      constructor() {
        interval()
          .pipe(take(100))
          .subscribe((num: number) => this.list = [...this.list, { n: num }]);
      }
    
      scroll() {
        const item = Array.from(this.rows)[44];
    
        console.log(item.nativeElement.outerHTML);
        item.nativeElement.scrollIntoView();
      }
    }