使用 *ngIf 指令的 ng-container 意外行为

ng-container unexpected behavior with *ngIf directive

我的项目中有一个 ng-container,它应该 show/hide 我的 HTML 的一部分,具体取决于某个 属性。

当 属性 最初为 false,之后我将其设置为 true - ng-container 中的内容按预期显示。但是,当 属性 最初为真时 - 内容不会显示。

HTML代码:

<ion-item>
  <ng-container *ngIf="prop">
  <ion-item>
    <ion-label stacked  [innerHTML]="htmlString"></ion-label>
    <ion-checkbox (click)="checkboxClick($event)"></ion-checkbox>
  </ion-item>
  </ng-container>
  </ion-item>

这里有一个 EXAMPLE 的初始 属性 是假的。 改成true后显示内容

这里有一个 EXAMPLE 的初始 属性 为真。 什么也没有显示。

如果该值最初为真,如何显示内容?

好的,问题是您需要定义 ng-container 包含 ion-item 的内容。

Working stackblitz

Documented on the ionic framework site.

<ion-item>
  <ng-container *ngIf="prop" item-content> <!-- this right here -->
    <ion-item>
      <ion-label stacked  [innerHTML]="htmlString"></ion-label>
      <ion-checkbox (click)="checkboxClick($event)"></ion-checkbox>
    </ion-item>
  </ng-container>
</ion-item>

问题在于 ion-item 如何呈现其模板。因为您的容器内有一个 ion-label,所以 parent ion-item 假定您的项目内容在模板中找到的这个 ion-label 内;因此忽略所有其余部分。

所以问题不是真正的 ng-container 而是 ion-item 它本身,当它以 prop=false 开始时,它不会呈现直到 angular 检测到更改并构建代码的这个特定部分;因此 ion-item 得到正确构建。但是当它开始时 true ion-item 自己把它扔掉了。

整个ion-item模板:

template:
    '<ng-content select="[item-start],[item-left],ion-checkbox:not([item-end]):not([item-right])"></ng-content>' +
    '<div class="item-inner">' +
      '<div class="input-wrapper">' +
        '<ng-content select="ion-label"></ng-content>' +
        '<ion-label *ngIf="_viewLabel">' +
          '<ng-content></ng-content>' +
        '</ion-label>' +
        '<ng-content select="ion-select,ion-input,ion-textarea,ion-datetime,ion-range,[item-content]"></ng-content>' +
      '</div>' +
      '<ng-content select="[item-end],[item-right],ion-radio,ion-toggle"></ng-content>' +
      '<ion-reorder *ngIf="_hasReorder"></ion-reorder>' +
    '</div>' +
'<div class="button-effect"></div>'

ion-item.ts line 274

如下所示,它查找 ion-label(第一行 select="ion-label"),如果找到,则将其用作项目的内容,否则创建一个新的 ion-label,其中包含您的 ion-item 的内容 (ng-content)。

ion-item模板的相关部分:

'<ng-content select="ion-label"></ng-content>' +
'<ion-label *ngIf="_viewLabel">' +
    '<ng-content></ng-content>' +
'</ion-label>' +
'<ng-content select="ion-select,ion-input,ion-textarea,ion-datetime,ion-range,[item-content]"></ng-content>' +

最终,这只是组件之间的冲突,因为您在另一个组件中使用一个 ion-item

解决这个问题的方法是使用<ng-container *ngIf="prop" item-content>(正如@Jacques 的建议),它将使插槽被之前描述的第三个插槽捕获,该插槽选择 [item-content] 作为目标而不是尽管 child ion-item.

上有 ion-label,但仍丢失了内容
'<ng-content select="ion-select,ion-input,ion-textarea,ion-datetime,ion-range,[item-content]"></ng-content>' +

Disclaimer: I only give my answer because the previous answer doesn't explain why this happen, consider this a complement.