I have a Dto which has a child Dto of the same class like so:
export interface KeywordDto {
children?: null | Array<KeywordDto>;
id?: number;
name?: null | string;
parent?: KeywordDto;
}
And the nested limit in theory can be unlimited (it won't be), but the point is that we won't know how many times this will be nested. So I want to have a method that can take a KeywordDto
, check for children then render that child and do the same for that Dto, and so on...
Here is my current attempt:
<mat-accordion multi>
<mat-expansion-panel *ngFor="let keyword of keywords">
<mat-expansion-panel-header>
<mat-panel-title>
{{ keyword.name }}
</mat-panel-title>
</mat-expansion-panel-header>
<div [innerHTML]="renderKeywordChildren(keyword)"></div>
</mat-expansion-panel>
</mat-accordion>
renderKeywordChildren(keyword: KeywordDto) {
if (keyword.children?.length! > 0) {
return `<mat-accordion multi>
<mat-expansion-panel *ngFor="{{let keyword of keywords}}">
<mat-expansion-panel-header>
<mat-panel-title>
{{ keyword.name }}
</mat-panel-title>
</mat-expansion-panel-header>
<div [innerHTML]="renderKeywordChildren(keyword)"></div>
</mat-expansion-panel>
</mat-accordion>`;
}
return;
}
So the issue with this is that the returning string doesn't know about the Angular templating, it will just print out {{ keyword.name }}
.
CodePudding user response:
Interesting question!
Your expected result will be nesting of the same template based on children
.
Besides using <ng-template>
with *ngIf
will be simpler, the critical point is how to pass the value into the nested template and how the nested template uses the received value as variable.
<ng-container
[ngTemplateOutlet]="keywordTemp"
[ngTemplateOutletContext]="{ keywords: keywords }"
>
</ng-container>
<ng-template #keywordTemp let-keywords="keywords">
<mat-accordion multi>
<mat-expansion-panel *ngFor="let keyword of keywords">
<mat-expansion-panel-header>
<mat-panel-title>
{{ keyword.name }}
</mat-panel-title>
</mat-expansion-panel-header>
<ng-container
*ngIf="(keyword.children?.length ?? 0) > 0"
[ngTemplateOutlet]="keywordTemp"
[ngTemplateOutletContext]="{ keywords: keyword.children }"
>
</ng-container>
</mat-expansion-panel>
</mat-accordion>
</ng-template>
Note: You may compare the previous version with the current version which improves in reducing code duplication.