Reputation: 6968
I'm trying to display a table and expand the rows when they are clicked to show some additional information.
I have the following HTML / TS displaying the table without issue, but when I add the connect code - the rows don't react on click and rows is printed as "[]" in the console..
Html:
<div class="example-container mat-elevation-z8">
<mat-table #table [dataSource]="dataSource">
<!-- Position Column -->
<ng-container matColumnDef="Name">
<mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
<mat-cell *matCellDef="let apptestlist"> {{apptestlist.Name}} </mat-cell>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="AppCount">
<mat-header-cell *matHeaderCellDef> Application Count </mat-header-cell>
<mat-cell *matCellDef="let apptestlist"> {{apptestlist.Apps.length}} </mat-cell>
</ng-container>
<!-- Expanded Content Column - The detail row is made up of this one column -->
<ng-container matColumnDef="expandedDetail">
<mat-cell *matCellDef="let apptestlist">
The symbol for {{apptestlist.Name}} is Banana
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"
matRipple
class="element-row"
[class.expanded]="expandedElement == row"
(click)="expandedElement === row? expandedElement = null : expandedElement = row"></mat-row>
<mat-row *matRowDef="let row; columns: ['expandedDetail']; when: isExpansionDetailRow"
[@detailExpand]="row.element == expandedElement ? 'expanded' : 'collapsed'"
style="overflow: hidden">
</mat-row>
</mat-table>
</div>
TS:
import { Component, OnInit } from '@angular/core';
import { AppTestListService } from '../services/app-test-list-service'
import { AppTestList } from '../models/AppTestList';
import { DataSource } from '@angular/cdk/table';
import { Observable, of } from 'rxjs';
import { animate, state, style, transition, trigger } from '@angular/animations';
@Component({
selector: 'app-application-test-lists',
templateUrl: './application-test-lists.component.html',
styleUrls: ['./application-test-lists.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 ApplicationTestListsComponent implements OnInit {
constructor(private appTestListService: AppTestListService) { }
dataSource = new AppTestListDataSource(this.appTestListService);
displayedColumns = ['Name', 'AppCount'];
appTestLists: AppTestList[];
loading = true;
isExpansionDetailRow = (i: number, row: Object) => row.hasOwnProperty('detailRow');
expandedElement: any;
ngOnInit() {
}
}
export class AppTestListDataSource extends DataSource<any> {
constructor(private appTestListService: AppTestListService) {
super();
}
connect(): Observable<AppTestList[]> {
return this.appTestListService.list();
}
disconnect() {}
}
This renders nicely how I want it:
I want to be able to expand the rows and display some additional information e.g
<ng-container matColumnDef="expandedDetail">
<mat-cell *matCellDef="let apptestlist">
The symbol for {{apptestlist.Name}} is Banana
</mat-cell>
</ng-container>
However it's not working..
I've changed my connect method to the following but it appears to return before any changes have happened:
connect(): Observable<AppTestList[]> {
const rows = [];
let data = this.appTestListService.list();
data.forEach(element => rows.push(element, { detailRow: true, element }));
console.log(rows);
return of(rows);
}
list():
public list(): Observable<AppTestList[]> {
return this.httpClient
.get<AppTestList[]>(`${this.url}/${this.endpoint}`);
}
Upvotes: 0
Views: 978
Reputation: 11081
Because AppTestListService.list()
returns an Observable
with or without the records initially, it is being assigned to your data
variable and your forEach
, console.log
and return of(rows)
completes before your .get
is finished retrieving the records.
You will need to wrap that part in a subscribe to ensure that it happens when you know you have the data from the .get
Also Note:
{{apptestlist.Name}}
does not mean anything to your detail row, you may want{{apptestlist.element.Name}}
instead.
connect(): Observable<AppTestList[]> {
const rows = [];
this.appTestListService.list().subscribe(val=>{
val.forEach(element => rows.push(element, { detailRow: true, element }));
})
return of(rows);
}
Stackblitz
https://stackblitz.com/edit/angular-golnkq?embed=1&file=app/table-basic-example.html
Upvotes: 1