【问题标题】:Why ng-content selector is not working inside *ngFor为什么 ng-content 选择器在 *ngFor 中不起作用
【发布时间】:2018-05-03 15:08:49
【问题描述】:

Here is the stackblitz code.

如你所见

<div *ngFor="let number of numbers;let i = index">
        <div *ngIf="(number%2 !== 0);else even">
            <ul odd>{{number}}</ul>
        </div>
    <ng-template #even>
      <ul even>{{number}}</ul>
    </ng-template>    
</div>

我正在尝试使用 ng-content 选择器呈现值,但它在 *ngFor 循环中不起作用。为什么这样 ?如何使它工作?更像这个 img

我不想要两个 ngFor 循环,我希望让它与 ng-content 一起工作。

【问题讨论】:

  • @TarunLalwani:非常感谢。在选择您的答案之前,我一直在等待其他一些答案。也对您的答案投了赞成票:)。我已经应用了您提出的解决方法。选择您的答案以确认 ng-content 不会像我预期的那样工作。

标签: angular


【解决方案1】:

你不能这样做,没有两个循环。 ng-content 的原因是一个占位符,它接受内部的动态 html。现在,当您在代码中循环时,您不会为 evenodd 选择器分配任何内容。但是,如果您将代码更改为以下

<child>
    <div *ngFor="let number of numbers;let i = index" even>
        <div *ngIf="(number%2 !== 0);else even">
            <ul>{{number}}</ul>
        </div>
    <ng-template #even>
      <ul>{{number}}</ul>
    </ng-template>    
  <!-- <ul even>Why its rendering and not others??</ul> -->
    </div>
</child>

你会看到输出变为

这是因为ng-For 的输出没有分配给even 选择器。

如果你把模板改成下面

<child>
    <div *ngFor="let number of numbers;let i = index" odd>
        <div *ngIf="(number%2 !== 0)">
            <ul>{{number}}</ul>
        </div>
    </div>
    <div *ngFor="let number of numbers;let i = index" even>
    <div *ngIf="(number%2 == 0)">
      <ul>{{number}}</ul>
    </div>    
    </div>
</child>

会有用的

还请记住,在 ng-For 内,您不能将内容附加到 evenodd 部分,即使该功能可用,它也会用最后一个值覆盖该部分。

甚至将ng-for 排除在外。下面的代码

<child>
  <div>
    <div odd>
      This should be under odd
    </div>
  </div>
</child>

也不行

因此,Angular 不支持您尝试实现的目标以及尝试实现它的方式。

【讨论】:

    【解决方案2】:

    你可以用两个循环来做到这一点:

    <div>
        <ng-container *ngFor="let number of numbers; let isFirst=first">
            <h2 *ngIf="isFirst">Odd Numbers</h2>
          <p>{{(number%2>0? number : '')}}</p>
       </ng-container>
    
      <ng-container *ngFor="let number of numbers; let isFirst=first">
          <h2 *ngIf="isFirst">Even</h2>
          <p>{{(number%2==0? number : '')}}</p>
      </ng-container>
    </div>
    

    【讨论】:

    【解决方案3】:

    其中一种解决方案是对数字数组进行排序。您可以使用自己的管道:

    import { Pipe, PipeTransform } from '@angular/core';
    
    @Pipe({name: 'oddFirst'})
    export class OddFirstPipe implements PipeTransform {
    
      transform(numbers: number[], args: any[]): number[] {
        const odd = numbers.filter(num => num % 2 !== 0);
        const even = numbers.filter(num => num % 2 === 0);
        return [...odd, ...even];
      }
    
    }
    

    然后你可以在你的模板中使用它:

    <div *ngFor="let number of numbers | oddFirst">
            <div *ngIf="(number%2 !== 0);else even">
                <ul odd>{{number}}</ul>
            </div>
        <ng-template #even>
          <ul even>{{number}}</ul>
        </ng-template>    
    </div>
    

    【讨论】:

    • 我正在渲染的&lt;h1&gt; 标签呢?我不想要排序列表,所以我可以实现相同的 *ngIf 并拥有它。我不是在寻找这个解决方案:(
    【解决方案4】:

    你可以用纯 CSS 做到这一点。

    看看修改后的 StackBlitz。

    https://stackblitz.com/edit/angular-zto8w1?file=app/app.component.html

    CSS 显示网格可以创造奇迹。请记住,IE 不(完全)支持它。

    【讨论】:

    • 可以看到都在Even
    【解决方案5】:

    这是因为嵌套。

    我运行了一些experiments on stackblitz,似乎内容根本无法嵌套,我们不能为此责备*ngFor。即使在 for 循环中使用 ng-container 也无济于事。

    【讨论】:

      【解决方案6】:

      首先让我们看看投影/ngContent 是什么。
      投影是Angular中一个非常重要的概念。它使开发人员能够构建可重用的组件并使应用程序更具可扩展性和灵活性。

      用更简单的话来说,它有助于动态添加内容,这些内容可以来自服务器作为组件内的 html 或文本,而无需创建像 document.createtextnode() 这样的 DOM 节点。

      投影参考:https://angular-2-training-book.rangle.io/handout/components/projection.html

      Projection 类似于指令中的 angularjs 嵌入。 https://docs.angularjs.org/api/ng/directive/ngTransclude

      让我们跳到您的问题。
      没错,我们需要两个循环来重复奇数和偶数 acc 中的内容。根据您的要求。原因:ngFor 在 DOM 中添加相同模板的新实例。

      工作代码
      https://stackblitz.com/edit/angular-ymznfu?file=app%2Fapp.component.html

      示例:

      App.component.html

      <child>
          <ng-container odd>//this will work
           <ul>{{number[1]}}</ul>
          </ng-container>
       </child>
      

      child.component.html

      <ng-content select="[odd]"></ng-content>
      

      上面的例子可以正常工作,我们在 ngContent 中投影最外层的 dom 节点。

      您可以尝试投影下面的代码

      app.component.html

       <child>
              <ng-container>
                  <ng-content select="[odd]"></ng-content>
              </ng-container>
          </child>
      

      上面的代码不会显示原因 Angular 只检查组件中可用的最外层节点,即代码中的原因

      <ul odd>Something</ul>
      

      正在投射,而其他人则没有。

      【讨论】:

        猜你喜欢
        • 2018-03-28
        • 2019-03-30
        • 2018-04-30
        • 1970-01-01
        • 2023-03-09
        • 2017-06-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多