I'm trying to create a page where there is a bunch of mat-expansion-panels that each have their own content. The content is hardcoded, but rather than having each page on it's own component, I wanted to try and make one component that gets reused and interacts with a static service in order to be scalable as more content needs to be added, or if I were to connect it to a database in the future.
What I've Tried (Variation 1)
<article *ngIf="code$ | async as title">
<h1>{{title.title}}</h1>
<div *ngFor="section of title.sections | async">
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
{{sTitle}}
</mat-panel-title>
<mat-panel-description>
{{sDesc}}
</mat-panel-description>
</mat-expansion-panel-header>
<div>
{{sContent}}
</div>
</mat-expansion-panel>
</div>
</article>
What I've Tried (Variation 2)
<article *ngIf="code$ | async as title">
<h1>{{title.title}}</h1>
<div *ngFor="section of title.sections | async as section">
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
{{sTitle}}
</mat-panel-title>
<mat-panel-description>
{{sDesc}}
</mat-panel-description>
</mat-expansion-panel-header>
<div>
{{sContent}}
</div>
</mat-expansion-panel>
</div>
</article>
What I've Tried (Variation 3)
<article *ngIf="code$ | async as title">
<h1>{{title.title}}</h1>
<div *ngFor="section of title.sections | async">
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
{{this.sTitle}}
</mat-panel-title>
<mat-panel-description>
{{this.sDesc}}
</mat-panel-description>
</mat-expansion-panel-header>
<div>
{{this.sContent}}
</div>
</mat-expansion-panel>
</div>
</article>
What I've Tried (Variation 4)
<article *ngIf="code$ | async as title">
<h1>{{title.title}}</h1>
<div *ngFor="section of title.sections | async">
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
{{this.section.sTitle}}
</mat-panel-title>
<mat-panel-description>
{{this.section.sDesc}}
</mat-panel-description>
</mat-expansion-panel-header>
<div>
{{this.section.sContent}}
</div>
</mat-expansion-panel>
</div>
</article>
Snippet of Component.ts (everything is imported fine at the top)
code$: any;
constructor(
private pcts: StaticService,
private route: ActivatedRoute
){}
ngOnInit(){
this.code$ = this.route.paramMap.pipe(
map(params => {
const title = params.get('slug');
return this.pcts.pctSearch(title);
})
)
}
Service.ts
export interface tSect {
sTitle: string;
sDesc: string;
sContent: string;
}
export interface pct {
id: string;
title: string;
sections: tSect[];
}
...
{
id: "...",
title: "...",
sections: [
{sTitle: 'Test', sDesc: 'Test', sContent: 'test'},
{sTitle: 'Tes2t', sDesc: 'Test2', sContent: 'test2'},
],
},
...
pctSearch(slug: string) {
var __FOUND = -1;
for(var t = 0; t < this.pctarr.length; t++) {
if(this.pctarr[t].id == slug) {
__FOUND = t;
return this.pctarr[__FOUND];
}
}
}
I get an error saying that the property (sContent, sTitle, or sDesc) doesn't exist on the component.
The section should show a list of mat-expansion-panel(s) with the sections from the array in the service.
Put the *ngFor on the mat-expansion-panel and take out the | async
| async
in the *ngFor, since you have already applied the pipe to the title
in the *ngIf.
Edit:
Your pctSearch function should be:
pctSearch(slug: string) {
return this.pctarr.filter(pct => pct.title === slug);
}
Keep in mind this will return you an array of pct's that match the slug. So if you just want the first element than just grab that first index.
Edit 2:
It was just a small error, you were missing "let" in your *ngFor. You also need to use the actual element in the loop when asking for the properties like sTitle, etc. Also in your component where you declare code$ you should also declare it's type instead of any to Observable (change any to whatever your type is).
So you're template would look like this:
<mat-expansion-panel *ngFor="let section of title.sections">
<mat-expansion-panel-header>
<mat-panel-title>
{{section.sTitle}}
</mat-panel-title>
<mat-panel-description>
{{section.sDesc}}
</mat-panel-description>
</mat-expansion-panel-header>
<div>
{{section.sContent}}
</div>
</mat-expansion-panel>
Also in your component you should declare code$ like this:
code$: Observable<any>;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.