深度嵌套的 ng-container 元素能否在 Angular 布局组件中正确渲染内容?

问题描述 投票:0回答:1

在我的 Angular 应用程序中,我使用 CSS 开发了一个具有两列的布局组件。在此布局组件内,我使用

ng-content
为旁白和主要内容定义了占位符。

旁白和主要部分的数据是从服务器获取的。在加载阶段,会设置一个

loading
标志来指示正在获取数据。成功检索数据后,会从可观察对象中返回一个
isSuccess
标志以及响应。

为了模拟这种行为,我使用 RxJS 中的

data$
运算符创建了一个模拟
of
可观察对象。此可观察量包括模仿异步数据检索过程的延迟。

布局未正确渲染旁白和主要内容。出现此问题的原因是

ng-content
指令直接需要属性
aside
main
,但它们深深嵌套在
ng-container
内部。

问题是,可以修改此设置以正确呈现内容吗?

这是修改后的代码:

import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { delay, of, startWith } from 'rxjs';
import 'zone.js';

@Component({
  selector: 'layout',
  standalone: true,
  template: `
    <div class="container">
      <aside>
        <ng-content select="[aside]"></ng-content>
      </aside>
      <main>
        <ng-content select="[main]"></ng-content>
      </main>
    </div>
  `,
  styles: [`.container {display:grid; grid-template-columns: 1fr 2fr} `],
})
export class LayoutComponent {}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [LayoutComponent, CommonModule],
  template: `
    <layout>
      <ng-container *ngIf="data$ | async as result">
        <div *ngIf="result.loading">loading...</div>
        <ng-container *ngIf="result.isSuccess">
          <div aside>aside content: {{ result.response.aside | json }}</div>
          <div main>main content: {{ result.response.main | json }}</div>
        </ng-container>
      </ng-container>
    </layout>
  `,
})
export class App {
  data$ = of<any>({
    response: { aside: [1, 2, 3, 4], main: [10, 12, 13, 14] },
    isSuccess: true,
  }).pipe(delay(1 * 1000), startWith({ loading: true }));
}

bootstrapApplication(App);

这是代码的链接:StackBlitz

javascript angular typescript rxjs
1个回答
0
投票

ng-content
标签必须出现在顶层,以便内容投影可见。

所以我重构了 HTML,以便我们获取数据并根据是否满足所有条件有条件地显示内容,然后使用

if else (ng-template)
我们可以显示加载部分!

请随意修改代码以满足您的要求!

完整代码:

import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { delay, of, startWith } from 'rxjs';
import { endWith } from 'rxjs/operators';
import 'zone.js';
console.clear();

@Component({
  selector: 'layout',
  standalone: true,
  template: `
    <div class="container">
      <aside>
        <ng-content select="[aside]"></ng-content>
      </aside>
      <main>
        <ng-content select="[main]"></ng-content>
      </main>
    </div>
  `,
  styles: [`.container {display:grid; grid-template-columns: 1fr 2fr} `],
})
export class LayoutComponent {}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [LayoutComponent, CommonModule],
  template: `
    <ng-container *ngIf="data$ | async as result">
      <layout *ngIf="result.isSuccess;else loading">
        <div aside>aside content: {{ result.response.aside | json }}</div>
        <div main>main content: {{ result.response.main | json }}</div>
      </layout>
    </ng-container>
    <ng-template #loading>
      <div>loading...</div>
    </ng-template>
  `,
})
export class App {
  name = 'Angular';

  data$ = of<any>({
    response: { aside: [1, 2, 3, 4], main: [10, 12, 13, 14] },
    isSuccess: true,
  }).pipe(delay(1 * 1000), startWith({ loading: true }));
}

bootstrapApplication(App);

Stackblitz 演示

© www.soinside.com 2019 - 2024. All rights reserved.