I have a Material table with expanded detail rows, inspired by that example (4 columns data + 1 action column for expanding rows).
Inside the detail rows template, there is a chart defined in another component. That component needs an object as input parameter which is the result of a function that use the detail row template matCellDef object as parameter.
The problem is the chart component received undefined
as input data.
main.component.html
with the table
<table mat-table
[dataSource]="accounts" multiTemplateDataRows
class="mat-elevation-z8">
<ng-container matColumnDef="crypto">
<th mat-header-cell *matHeaderCellDef>Crypto</th>
<td mat-cell *matCellDef="let account">
<div>
<div>{{ account.code }}</div>
<div class="crypto-label">{{ account.libel }}</div>
</div>
</td>
</ng-container>
<ng-container matColumnDef="price">
<th mat-header-cell *matHeaderCellDef>Price</th>
<td mat-cell *matCellDef="let account">
{{ account.price | currency:'EUR':'symbol':'1.2-2' }}
</td>
</ng-container>
<ng-container matColumnDef="holdings">
<th mat-header-cell *matHeaderCellDef>Holdings</th>
<td mat-cell *matCellDef="let account">
<div>
<div>{{ account.balance | cryptoBalanceFormat }}</div>
<div class="amount-price">12 345,99 € </div>
</div>
</td>
</ng-container>
<ng-container matColumnDef="last24h">
<th mat-header-cell *matHeaderCellDef>24H</th>
<td mat-cell *matCellDef="let account">
<div>
<div class="trend-icon"><mat-icon>trending_up</mat-icon></div>
<div class="crypto-label">3,23%</div>
</div>
</td>
</ng-container>
<ng-container matColumnDef="expand">
<th mat-header-cell *matHeaderCellDef aria-label="row actions"> </th>
<td mat-cell *matCellDef="let element">
<button mat-icon-button aria-label="expand row" (click)="(expandedElement = expandedElement === element ? null : element); $event.stopPropagation()">
<mat-icon *ngIf="expandedElement !== element">keyboard_arrow_down</mat-icon>
<mat-icon *ngIf="expandedElement === element">keyboard_arrow_up</mat-icon>
</button>
</td>
</ng-container>
<!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->
<ng-container matColumnDef="expandedDetail">
<td mat-cell *matCellDef="let element" [attr.colspan]="displayedColumnsWithExpand.length">
<div class="example-element-detail"
[@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
<app-account-chart [datas]="getChartOptions(element)"></app-account-chart>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumnsWithExpand"></tr>
<tr mat-row *matRowDef="let element; columns: displayedColumnsWithExpand; "
class="example-element-row"
[class.example-expanded-row]="expandedElement === element"
(click)="expandedElement = expandedElement === element ? null : element">
</tr>
<tr mat-row *matRowDef="let element; columns: ['expandedDetail']" class="detail-row"></tr>
</table>
main.component.ts
export class CryptoComponent implements OnInit{
accounts!: CryptoAccount[];
displayedColumns = ['crypto', 'price', 'holdings', "last24h"];
displayedColumnsWithExpand = [...this.displayedColumns, 'expand'];
displaySpinner = false;
expandedElement: any;
constructor(
private readonly cryptoService: CryptoService
) {}
ngOnInit(): void {
this.getAccounts();
}
getAccounts(askRefresh = false) {
/* get datas */
}
getChartOptions(account: CryptoAccount): ChartData {
return {
legends: ["Mars", "Avril" ,"Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre", "Janvier", "Février"],
values: [140, 232, 101, 264, 90, 340, 250, 238, 111, 222, 342, 123]
};
}
}
chart.component.ts
export class AccountChartComponent {
@Input() datas!: any;
chartOption!: EChartsOption;
constructor() {
this.initGrid();
}
initGrid(): void {
console.log(this.datas);
this.chartOption = {
tooltip: {
trigger: "axis",
axisPointer: {
type: "cross",
label: {
backgroundColor: "#6a7985"
}
}
},
grid: {
left: "3%",
right: "4%",
bottom: "3%",
containLabel: true
},
xAxis: [
{
type: "category",
boundaryGap: false,
axisLabel: {
color: 'white',
},
data: ["Mars", "Avril" ,"Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre", "Janvier", "Février"]
}
],
yAxis: [
{
type: "value",
axisLabel: {
color: 'white',
},
}
],
series: [
{
name: "Nom_Crypto",
type: "line",
stack: "Total",
smooth: true,
lineStyle: {
width: 0
},
showSymbol: false,
areaStyle: {
opacity: 0.8,
color: new graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgb(55, 162, 255)'
},
{
offset: 1,
color: 'rgb(116, 21, 219)'
}
])
},
emphasis: {
focus: "series"
},
data: [140, 232, 101, 264, 90, 340, 250, 238, 111, 222, 342, 123]
}
]
};
}
}
The value of datas
is undefined
I think I've read that we can't pass parameters to child components from ng-container
because it's not in the dom (or something like that ...)
So my question is how can i do that 🙃 ?
You call this.initGrid() in the constructor. Move it to OnInit(or better to OnChange), and it'll help you
Simple demo: https://stackblitz.com/edit/angular-u6ag8d?file=src/main.component.html