【问题标题】:How can I create an embedded ngFor inside of an ngIf statement?如何在 ngIf 语句中创建嵌入式 ngFor?
【发布时间】:2020-10-23 09:51:44
【问题描述】:

我要做什么

我正在尝试创建一个页面,其中有一堆垫子扩展面板,每个面板都有自己的内容。内容是硬编码的,但是我不想让每个页面都在它自己的组件上,我想尝试制作一个可以重用并与静态服务交互的组件,以便在需要添加更多内容时可扩展,或者如果我是将来将其连接到数据库。

我的尝试

我的尝试(变体 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>

我的尝试(变体 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>

我的尝试(变体 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>

我的尝试(变体 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>

其他代码

Component.ts 的片段(一切都在顶部很好地导入)

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);
      })
    )
  }

服务.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];
      }
    }
  }

会发生什么?

我收到一条错误消息,指出组件上不存在该属性(sContent、sTitle 或 sDesc)。

预期结果

该部分应显示 mat-expansion-panel(s) 列表,其中包含服务中数组中的部分。

【问题讨论】:

    标签: angular service angular-material angular9


    【解决方案1】:

    将 *ngFor 放在 mat-expansion-panel 上并取出 *ngFor 中的 | async,因为您已经将管道应用于 *ngIf 中的 title。

    编辑:

    您的 pctSearch 函数应该是:

    pctSearch(slug: string) {
        return this.pctarr.filter(pct => pct.title === slug);
    }
    

    请记住,这将返回一个与 slug 匹配的 pct 数组。因此,如果您只想要第一个元素,而不仅仅是获取第一个索引。

    编辑 2:

    这只是一个小错误,您的 *ngFor 中缺少“let”。在请求诸如 sTitle 等属性时,您还需要在循环中使用实际元素。此外,在您声明 code$ 的组件中,您还应该将其类型而不是 any 声明为 Observable(将 any 更改为您的任何类型) .

    所以你的模板应该是这样的:

    <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>
    

    同样在你的组件中你应该像这样声明 code$:

    code$: Observable<any>;
    

    【讨论】:

    • @HarrisonMayotte 你的 pcts.pctSearch(title) 方法是什么样的?
    • @HarrisonMayotte,你的 if 条件不应该是 if (this.pctarr[t].title === slug) 吗?
    • 我不明白如果您尝试比较和 id 到标题,您期望该方法如何工作
    • 在您的组件中,当您管道 paramMap 时,您正在使用返回数组的 map 运算符,我猜这就是您收到错误的原因。抓住数组的第一个索引,你应该很好。您可以将 (code$ | async)[0] 作为标题。如果你不想返回一个数组,你可以使用点击操作符
    • 我收回我所说的关于地图操作员的话。如果您可以通过一个简单的示例创建一个堆栈闪电战,我可以尝试提供帮助。这是一个非常简单的问题,我不知道你为什么会遇到这个问题。
    猜你喜欢
    • 1970-01-01
    • 2022-10-15
    • 1970-01-01
    • 2023-04-08
    • 2017-05-23
    • 2017-07-22
    • 2018-08-17
    • 2022-11-23
    • 1970-01-01
    相关资源
    最近更新 更多