Контекст:
У меня есть компонент, который загружает <table mat-table>
с данным источником данных. Я добавил (keydown) функцию к <tr mat-row>
.
Эта функция позволяет мне смещать выделение строк вверх и вниз при нажатии клавиш со стрелками вверх / вниз.
Проблемы:
Чтобы выполнить функцию (keydown), мне нужно либо щелкнуть одну из строк таблицы, чтобы установить фокус, либо использовать вкладку для нескольких элементов, чтобы в конечном итоге сосредоточиться на строках таблицы.
Функция (keydown) изменяет только подсветку строк, но не фокус. Поэтому, если я нажму стрелку вниз, следующий ряд будет подсвечен, но контур: focus останется в предыдущем ряду.
Я пробовал несколько решений, и, похоже, не могуСфокусируйте теги <tr>
, не нажимая / TabДиректива автофокуса не поддерживается для тегов <tr>
. Используя .focus () ошибки, утверждая, что .focus () не является функцией, даже если я приведу его к типу HTMLElement.
Пример:
let firstRow = this.dataSource.connect().value[0] as unknown as HTMLTableRowElement;
firstRow.focus();
ERROR TypeError: firstRow.focus is not a function
Я также пытался применить tabIndex = "0" к строке мата, но он не стал первым элементом с возможностью табуляции на странице.
Таблица может быть отсортирована, поэтомуЯ использую dataSource.connect (). Value [0], чтобы найти первую строку, а не dataSource.data [0].
Это связано с тем, что dataSource.data [0] предоставлял предварительно отсортированный массив, который побеждал назначение функции стрелок вверх / вниз.
Компонент TS:
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<TableGrid> = null;
displayedColumns = [
'locked',
'includeRe',
'includeMv'];
selection = new SelectionModel<TableGrid>(false, []);
selectedRowId = 0;
selectedRowIndex = 0;
constructor( private tableService: TableService) { }
ngOnInit() {
this.tableService.get();
this.tableService.tableGrid
.subscribe(result => {
this.selectedRowId = 0;
this.dataSource = new MatTableDataSource(result);
this.dataSource.sort = this.sort;
if (this.dataSource.data.length > 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);
}
}
}
}
HTML:
<div class="container">
<div class="table-container">
<table mat-table [dataSource]="dataSource" matSort aria-label="Elements">
<ng-container matColumnDef="locked">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Locked</th>
<td mat-cell *matCellDef="let row">
<i *ngIf="row.locked === true" class="material-icons">lock</i>
</td>
</ng-container>
<ng-container matColumnDef="includeRe">
<th mat-header-cell *matHeaderCellDef mat-sort-header>RE</th>
<td mat-cell *matCellDef="let row">
<i *ngIf="row.includeRe === true" class="material-icons">house</i>
</td>
</ng-container>
<ng-container matColumnDef="includeMv">
<th mat-header-cell *matHeaderCellDef mat-sort-header>MV</th>
<td mat-cell *matCellDef="let row">
<i *ngIf="row.includeMv === true" class="material-icons">directions_car</i>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky:true"></tr>
<tr mat-row tabIndex="0" *matRowDef="let row; columns: displayedColumns;"
(click)="onRowClicked(row)"
(keydown)="tableKeydown($event)"
[ngClass] = "{'highlight' : row.id == selectedRowId}">
</tr>
</table>
</div>
</div>
Желаемая функциональность:
Я хотел бы установить: focusАтрибут для первой <tr>
таблицы в init, так что функция (keydown) может быть сразу использована.
Я также хотел бы получить функцию (keydown) для установки: focus на <tr>
tags.
Чего я пытаюсь избежать
Я бы хотел избежать создания собственного класса фокусировки для воспроизведения эффекта контура фокуса. Я также хотел бы избежать отключения фокуса фокуса на строках таблицы. Я хочу поставить псевдокласс: focus на <tr>
. Если это невозможно, я рассмотрю альтернативы.
Я могу добавить больше информации, если это необходимо, но я стараюсь сохранять ее относительно анонимной, поскольку это связано с работой.
Яотносительно новый для Angular, но в течение нескольких лет разрабатывался в React. Любой совет будет принят во внимание.
Спасибо.