无法在递归 Angular 表单上使用 ngIf 找到带路径的控件

Cannot Find Control with Path Using ngIf on Recursive Angular Form

Here is the stackblitz 下面的代码。 我正在使用 FormArrays 和子组件制作一个相当复杂的深层嵌套 Angular 表单。在大多数情况下,一切都按预期工作。 group 对象包含 conjunctorconditions[]groups[]groups[]是一个嵌套组,可以无限嵌套包含同一个对象。

目前,您可以选择“添加组”、“添加嵌套组”、“添加条件”、“删除组”和“删除条件”,以便创建嵌套表单对象。为此,应用程序分为 3 个组件:

AppComponent:包含 ng-containers 和 *ngFor 的主窗体以迭代组

GroupControlComponent:保存 AppComponent 内每个项目的逻辑,并与 AppComponent 做同样的事情,但条件和嵌套组

ConditionsForm:保存条件项的逻辑

还有一个 ActionsButtonsBarComponent 来容纳按钮以发出事件、添加和删除组和条件。

我试图在每第二组中做到这一点,有一个连词的输入。我一开始根本不想要它,因为我希望第一个始终为空。但是,在第二次及以后的情况下,我希望出现连词输入,提供“AND”或“OR”选项。当我创建它时,我收到错误:ERROR: Cannot find control with path: 'statement → groups → 1 → conjunctor 来自 AppComponent。

AppComponent 的外观如下:

<form [formGroup]="_form">
    <ng-container formGroupName="statement">
        <ng-container formArrayName="groups">
            <ng-container *ngFor="let group of _groupsFormArray?.controls; index as i">
         <div *ngIf="i > 0">
           <div [formGroupName]="i">
             <input type="text" formControlName="conjunctor">
           </div>
         </div>
            <app-group-control 
             (remove)="_delete(i)"
             [formControlName]="i"
             [formLabel]="'Group '+ (i + 1) + ':'">
            </app-group-control>
            </ng-container>
        </ng-container>
    </ng-container>
</form>

如您所见,有一个 div 包含 ngIf 逻辑:

<div *ngIf="i > 0">
  <div [formGroupName]="i">
    <input type="text" formControlName="conjunctor">
  </div>
</div>

这个方法不行,我试过的其他方法也不行。

到目前为止,我已经多次尝试将FormGroupName更改为groupsstatementsiindex,但没有任何改善。

我还尝试使用 @ViewChildren('templateRef') templateRefVar: QueryList<ElementRef>; 从 AppComponent 跟踪每个 ngFor 的实例,然后使用模板引用 #templateRefngFor 内部跟踪每个 ngFor 的实例。从那里,我使用 @Input() groupInstances 将此 templateRef.length 传递给我的子组件 GroupControlComponent,然后在内部使用 ngIf。这是我得到的最接近的,但问题是,每次满足 ngIf 条件时,它都会出现在组数组的每个实例上,包括第一个实例,并给我错误:ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: '0'. Current value: '1'.Here is a StackBlitz of the closest I've got using this method. And here is the StackBlitz 来自上面的代码。

如果您想了解有关此递归形式的更多信息,可以阅读

Stackblitz demo

让我们用 showConjunctor 替换 groupInstance 只是为了更清楚地说明它的用途。

你可以做到这一点 app.component.hml:

<app-group-control 
  #templateRef
  (remove)="_delete(i)"
  [formControlName]="i"
  [formLabel]="'Group '+ (i + 1) + ':'"
  [showConjunctor]="!((i + 1) % 2)">
</app-group-control>

我正在考虑 i,在上面的片段中,是 *ngFor 中当前循环的索引(就像在 Stackblitz 演示中一样)。

此外,从 app.component.html 中删除此部分:

<div *ngIf="i > 0">
  <div [formGroupName]="i">
    <input type="text" formControlName="conjunctor">
  </div>
</div>

[UPDATE]: 根据您的意见,如果您想全部使用连词 在嵌套组中,您可以在 GroupControlComponent (Stackblitz demo):

中将 @Input() showConjuntor 设置为 true
<ng-container formArrayName="groups">
  <app-group-control *ngFor="let s of _groupsFormArray?.controls; index as i"
                      (remove)="_deleteGroupFromArray(i)" 
                      [formControlName]="i"
                      [formLabel]="'Nested Group '+ (i + 1) + ':'"
                      [showConjunctor]="true">
  </app-group-control>
</ng-container>