title: How to autofocus a table row <tr> in Angular
body: <p><strong>Context:</strong></p>
  
  <p>I have a component that loads a <code>&lt;table mat-table&gt;</code> with a given data source. 
  I have added a (keydown) function to the <code>&lt;tr mat-row&gt;</code>. </p>
  
  <p>The function allows me to shift the row highlighting up and down the rows as I press the up/down arrow keys.</p>
  
  <p><strong>Issues:</strong></p>
  
  <ol>
  <li><p>In order for the (keydown) function to execute, I have to either click one of the table rows to set the focus, or use the Tab through multiple items to eventually focus on the table rows.</p></li>
  <li><p>The (keydown) function is only changing the highlighting of the rows, and not the :focus. So if I hit the down arrow, the next row down highlights, but the :focus outline remains on the previous row.</p></li>
  </ol>
  
  <p>I've tried a few solutions, and it seems I cannot focus the <code>&lt;tr&gt;</code> tags without clicking / Tabbing. The autofocus directive is not supported for <code>&lt;tr&gt;</code> tags. Using .focus() errors out, claiming that .focus() is not a function, even if I cast it to the HTMLElement type.</p>
  
  <p>Example:</p>
  
  <pre><code>let firstRow = this.dataSource.connect().value[0] as unknown as HTMLTableRowElement;
  firstRow.focus();
  </code></pre>
  
  <p><code>ERROR TypeError: firstRow.focus is not a function</code></p>
  
  <p>I have also tried applying tabIndex="0" to the mat-row, but it does not become the first tab-able element on the page.</p>
  
  <p>The table is sort-able, so I am using dataSource.connect().value[0] to find the first row, rather than dataSource.data[0]. </p>
  
  <p>This is because dataSource.data[0] was giving the pre-sorted array, which was defeating the purpose of the up/down arrow functionality.</p>
  
  <p><strong>TS Component:</strong></p>
  
  <pre><code>import { Component, OnInit, ViewChild } from '@angular/core';
  import { MatSort } from '@angular/material/sort';
  import { MatTableDataSource } from '@angular/material/table';
  import { TableService } from '../table.service';
  import { SelectionModel } from '@angular/cdk/collections';
  import { TableGrid } from '../TableGrid';
  
  @Component({
    selector: 'app-table',
    templateUrl: './table.component.html',
    styleUrls: ['./table.component.css']
  })
  export class TableComponent implements OnInit {
  
    @ViewChild(MatSort, { static: true }) sort: MatSort;
    dataSource: MatTableDataSource&lt;TableGrid&gt; = null;
    displayedColumns = [
      'locked',
      'includeRe',
      'includeMv'];
  
    selection = new SelectionModel&lt;TableGrid&gt;(false, []);
    selectedRowId = 0;
    selectedRowIndex = 0;
  
    constructor( private tableService: TableService) { }
  
  
    ngOnInit() {
      this.tableService.get();
      this.tableService.tableGrid
        .subscribe(result =&gt; {
          this.selectedRowId = 0;
          this.dataSource = new MatTableDataSource(result);
          this.dataSource.sort = this.sort;
          if (this.dataSource.data.length &gt; 0) {
            this.onRowClicked(this.dataSource.data[0]);
          }
        });
    }
  
    onRowClicked(row) {
      this.selection.clear();
      this.selection.select(row);
      this.selectedRowId = row.id;
      this.selectedRowIndex = this.dataSource.connect().value.indexOf(row);
      this.tableService.setId(row.id, row.name, row.locked, row.isDeleteable, row.includeHistory);
  
    }
  
    tableKeydown(event: KeyboardEvent) {
      if (!this.selection.isEmpty()) {
        let newSelection;
        const currentIndex = this.selectedRowIndex;
        if (event.key === 'ArrowDown') {
          newSelection = this.dataSource.connect().value[currentIndex + 1];
        } else if (event.key === 'ArrowUp') {
          newSelection = this.dataSource.connect().value[currentIndex - 1];
        }
        if (newSelection) {
          this.selectedRowId = newSelection.id;
          this.onRowClicked(newSelection);
        }
      }
    }
  }
  </code></pre>
  
  <p><strong>HTML:</strong></p>
  
  <pre><code>&lt;div class="container"&gt;
    &lt;div class="table-container"&gt;
      &lt;table mat-table [dataSource]="dataSource" matSort aria-label="Elements"&gt;
        &lt;ng-container matColumnDef="locked"&gt;
          &lt;th mat-header-cell *matHeaderCellDef mat-sort-header&gt;Locked&lt;/th&gt;
          &lt;td mat-cell *matCellDef="let row"&gt;
            &lt;i *ngIf="row.locked === true" class="material-icons"&gt;lock&lt;/i&gt;
          &lt;/td&gt;
        &lt;/ng-container&gt;
        &lt;ng-container matColumnDef="includeRe"&gt;
          &lt;th mat-header-cell *matHeaderCellDef mat-sort-header&gt;RE&lt;/th&gt;
          &lt;td mat-cell *matCellDef="let row"&gt;
            &lt;i *ngIf="row.includeRe === true" class="material-icons"&gt;house&lt;/i&gt;
          &lt;/td&gt;
        &lt;/ng-container&gt;
        &lt;ng-container matColumnDef="includeMv"&gt;
          &lt;th mat-header-cell *matHeaderCellDef mat-sort-header&gt;MV&lt;/th&gt;
          &lt;td mat-cell *matCellDef="let row"&gt;
            &lt;i *ngIf="row.includeMv === true" class="material-icons"&gt;directions_car&lt;/i&gt;
          &lt;/td&gt;
        &lt;/ng-container&gt;
        &lt;tr mat-header-row *matHeaderRowDef="displayedColumns; sticky:true"&gt;&lt;/tr&gt;
        &lt;tr mat-row tabIndex="0" *matRowDef="let row; columns: displayedColumns;"
            (click)="onRowClicked(row)"
            (keydown)="tableKeydown($event)"
            [ngClass] = "{'highlight' : row.id == selectedRowId}"&gt;
        &lt;/tr&gt;
      &lt;/table&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p><strong>Desired Functionality:</strong></p>
  
  <p>I would like to set the :focus attribute to the first <code>&lt;tr&gt;</code> of the table on init, so that the (keydown) function is immediately usable.</p>
  
  <p>I would also like to get the (keydown) function to set the :focus on the <code>&lt;tr&gt;</code> tags.</p>
  
  <p><strong>What I'm trying to avoid</strong></p>
  
  <p>I would like to avoid creating a custom focus class to reproduce the focus outline effect. I would also like to avoid disabling the focus-outline on table-rows. What I want, is to put the :focus pseudo-class on the <code>&lt;tr&gt;</code>. If this is impossible, I will consider alternatives.</p>
  
  <p>I can add more info if needed, but I'm trying to keep it relatively anonymous as this is work-related.</p>
  
  <p>I'm relatively new to Angular, but have developed for a few years in React. Any advice would be appreciated. </p>
  
  <p>Thank you.</p>