Я сделал нестандартный компонент из Таблица угловых материалов . По сути, это рекурсивная таблица, в которой при щелчке на строке отображается подтаблица, а при щелчке на строке последующего - подтаблица. Требуется рекурсивный шаблон. Входные данные таблицы достаточно велики и принимают форму JSON с массивами JSON и т. Д. Этот формат был выбран остальной частью проекта и является негибким.
Данные хранятся в переменной с именем data
. В моей таблице есть поле ввода для изменения записей в data
, и я проверил, работает ли он должным образом, моя проблема в том, что если обновление data
извне таблицы, представление таблицы не изменяется, обновление не происходит. Меня это удивляет, так как используется привязка при передаче data
компоненту. Я новичок в Angular и пока не чувствую себя комфортно с Subjects
и Observables
, поэтому я не смотрел в этом направлении.
Вот код.
Для рекурсивного компонента:
@Component({
selector: 'app-rectable',
template: `
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<div class="example-container mat-elevation-z8">
<mat-table [dataSource]="theData">
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef> channel </mat-header-cell>
<mat-cell *matCellDef="let element">
<button *ngIf="element.isexpandable" mat-icon-button (click)="element.isexpanded = !element.isexpanded;">
<mat-icon class="mat-icon-rtl-mirror">
{{element.isexpanded ? 'expand_more' : 'chevron_right'}}
</mat-icon>
</button>
<mat-form-field class="example-full-width">
<input matInput [(ngModel)]="element.name" (input)="update($event)">
</mat-form-field>
</mat-cell>
</ng-container>
<ng-container matColumnDef="min">
<mat-header-cell *matHeaderCellDef> min </mat-header-cell>
<mat-cell *matCellDef="let element">
<input matInput type=number [(ngModel)]="element.min" (input)="update($event)">
</mat-cell>
</ng-container>
<ng-container matColumnDef="max">
<mat-header-cell *matHeaderCellDef> max </mat-header-cell>
<mat-cell *matCellDef="let element">
<input matInput type=number [(ngModel)]="element.max" (input)="update($event)">
</mat-cell>
</ng-container>
<ng-container matColumnDef="value">
<mat-header-cell *matHeaderCellDef> value </mat-header-cell>
<mat-cell *matCellDef="let element">
{{element.value}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="expandedDetail">
<mat-cell *matCellDef="let detail">
<app-rectable *ngIf="detail.element.isexpandable" [array]="detail.element.variables" [isTop]="false">
</app-rectable>
</mat-cell>
</ng-container>
<div *ngIf="isTop">
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
</div>
<mat-row *matRowDef="let row; columns: displayedColumns;" matRipple class="element-row" [class.expanded]="row.isexpanded" >
</mat-row>
<mat-row *matRowDef="let row; columns: ['expandedDetail']; when: isExpansionDetailRow" [@detailExpand]="row.element.isexpanded ? 'expanded' : 'collapsed'" style="overflow: hidden">
</mat-row>
</mat-table>
</div>
<div *ngIf="!theData.value.length" > EMPTY DATA INPUT </div>
`,
styleUrls: ['./rectable.component.css'],
animations: [
trigger('detailExpand', [
state('collapsed', style({ height: '0px', minHeight: '0', visibility: 'hidden' })),
state('expanded', style({ height: '*', visibility: 'visible' })),
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
]),
],
})
export class RectableComponent implements OnInit {
@Input() array;
@Input() isTop: boolean;
theData = [];
displayedColumns = ["name", "min", "max", "value"];
isExpansionDetailRow = (i: number, row: Object) => row.hasOwnProperty('detailRow');
constructor() {
}
ngOnInit() {
this.theData = observableOf(this.array);
}
}
html-компонент корневого компонента
<app-rectable [array]='data' [isTop]="true"></app-rectable>
Где data
- это объект JSON, который я предпочитаю не указывать здесь явно.