As mentioned in the comment, there is no point to split the store and employees data into separate array if you are constructing the nested table as the screenshot.
Updated
Well, if both stores and employees data come from separate arrays, you should join it together in your back-end API/database so you will need single API call. (Unfortunately you didn't cover on how you obtain these data from the back-end API or database, hence I will not cover this topic).
If you are not able/granted to build/change the API for the mentioned joining data, you can look for joining both storeTableData and employeeTableData in the front-end:
const storeWithEmployeesData: any[] = storeTableData.map((store) => ({
...store,
employees: employeeTableData.filter((e) => store.StoreID == e.StoreID)
}));
Taking the example for my written answer on Expanding multiple rows in a nested mat table in Angular not working, you can construct the nested table in the column as well.
Note that if you implement the sorting feature in the nested table, your employees array should be transformed to MatTableDataSource<T> type and assign the MatSort instance accordingly.
<table
mat-table
#outerSort="matSort"
[dataSource]="dataSource"
multiTemplateDataRows
class="mat-elevation-z8"
matSort
>
<ng-container matColumnDef="Store">
<th mat-header-cell *matHeaderCellDef mat-sort-header=>Store</th>
<td mat-cell *matCellDef="let element">{{element.Store}}</td>
</ng-container>
<ng-container matColumnDef="address">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Address</th>
<td mat-cell *matCellDef="let element">{{element.address}}</td>
</ng-container>
<ng-container matColumnDef="employees">
<th mat-header-cell *matHeaderCellDef>Employees</th>
<td mat-cell *matCellDef="let element">
<table
#innerTables
mat-table
#innerSort="matSort"
[dataSource]="element.employees"
matSort
>
<ng-container
*ngFor="let innerColumn of innerDisplayedColumns"
[matColumnDef]="innerColumn"
>
<th mat-header-cell *matHeaderCellDef [mat-sort-header]="innerColumn">
{{innerColumn}}
</th>
<td mat-cell *matCellDef="let element">{{element[innerColumn]}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="innerDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: innerDisplayedColumns;"></tr>
</table>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
<tr mat-row *matRowDef="let element; columns: columnsToDisplay;"></tr>
</table>
import {
QueryList,
ViewChild,
ViewChildren,
} from '@angular/core';
import {
MatTable,
MatTableDataSource,
MatTableModule,
} from '@angular/material/table';
import { MatSort, MatSortModule } from '@angular/material/sort';
@ViewChild('outerSort', { static: true }) sort: MatSort;
dataSource: MatTableDataSource<any>;
@ViewChildren('innerSort') innerSort: QueryList<MatSort>;
@ViewChildren('innerTables') innerTables: QueryList<MatTable<any>>;
columnsToDisplay = ['Store', 'address', 'employees'];
innerDisplayedColumns = ['Name', 'Role'];
ngOnInit() {
let storesData: any[] = this.stores.map((store) => ({
...store,
employees: new MatTableDataSource(store.employees || []),
}));
this.dataSource = new MatTableDataSource(storesData);
this.dataSource.sort = this.sort;
}
ngAfterViewInit() {
this.innerTables.forEach((table, index) => {
const dataSource = table.dataSource as MatTableDataSource<any>;
dataSource.sort = this.innerSort.toArray()[index];
});
}
Demo @ StackBlitz
Storearray, which contains bothstoreinfo andemployeesarray into two separate arrays a good choice. Assume that when generating the employee table in the employees column (based on your screenshot) will need additional effort to find the employees that fall under which store.angular-materialbut there is no mention of that in the question. If using angular material use @YongShun answer