无法在递归 Angular 表单上使用 ngIf 找到带路径的控件
Cannot Find Control with Path Using ngIf on Recursive Angular Form
Here is the stackblitz 下面的代码。
我正在使用 FormArrays 和子组件制作一个相当复杂的深层嵌套 Angular 表单。在大多数情况下,一切都按预期工作。 group
对象包含 conjunctor
、conditions[]
和 groups[]
。 groups[]
是一个嵌套组,可以无限嵌套包含同一个对象。
目前,您可以选择“添加组”、“添加嵌套组”、“添加条件”、“删除组”和“删除条件”,以便创建嵌套表单对象。为此,应用程序分为 3 个组件:
AppComponent:包含 ng-container
s 和 *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更改为groups
、statements
、i
、index
,但没有任何改善。
我还尝试使用 @ViewChildren('templateRef') templateRefVar: QueryList<ElementRef>;
从 AppComponent 跟踪每个 ngFor
的实例,然后使用模板引用 #templateRef
在 ngFor
内部跟踪每个 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 来自上面的代码。
如果您想了解有关此递归形式的更多信息,可以阅读
让我们用 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>
Here is the stackblitz 下面的代码。
我正在使用 FormArrays 和子组件制作一个相当复杂的深层嵌套 Angular 表单。在大多数情况下,一切都按预期工作。 group
对象包含 conjunctor
、conditions[]
和 groups[]
。 groups[]
是一个嵌套组,可以无限嵌套包含同一个对象。
目前,您可以选择“添加组”、“添加嵌套组”、“添加条件”、“删除组”和“删除条件”,以便创建嵌套表单对象。为此,应用程序分为 3 个组件:
AppComponent:包含 ng-container
s 和 *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更改为groups
、statements
、i
、index
,但没有任何改善。
我还尝试使用 @ViewChildren('templateRef') templateRefVar: QueryList<ElementRef>;
从 AppComponent 跟踪每个 ngFor
的实例,然后使用模板引用 #templateRef
在 ngFor
内部跟踪每个 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 来自上面的代码。
如果您想了解有关此递归形式的更多信息,可以阅读
让我们用 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>