- 首页
- 其他开发
- 无法在递归角形式上使用 ngIf 找到带路径的控件
无法在递归角形式上使用 ngIf 找到带路径的控件
[英] Cannot Find Control with Path Using ngIf on Recursive Angular Form
本文介绍了无法在递归角形式上使用 ngIf 找到带路径的控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
这是下面代码的stackblitz.我正在使用 FormArrays 和子组件制作一个相当复杂的深度嵌套 Angular 表单.在大多数情况下,一切都按预期工作.group
对象包含一个 conjunctor
、conditions[]
和 groups[]
.groups[]
是一个嵌套组,可以无限嵌套包含同一个对象.
目前,您可以选择添加组"、添加嵌套组"、添加条件"、删除组"和删除条件"以便它创建一个嵌套的表单对象.为此,该应用程序分为 3 个组件:
AppComponent:使用 ng-container
s 和 *ngFor
保存主表单以遍历组
GroupControlComponent:在 AppComponent 中保存每一项的逻辑,并与 AppComponent 做同样的事情,但对于条件和嵌套组
ConditionsForm:保存条件项的逻辑
还有一个 ActionsButtonsBarComponent 来保存按钮以发出事件、添加和删除组和条件.
我试图让每组都如此,Conjunctor 有一个输入.我在第一个实例上根本不想要它,因为我希望第一个始终为空.但是,在第 2 次及之后的实例中,我希望出现连接器输入,并提供AND"和AND"选项.或或".当我创建这个时,我收到错误:ERROR:找不到路径控制:'statement → groups → 1 → conjunctor
来自 AppComponent.
AppComponent 的外观如下:
<应用组控制(remove)="_delete(i)";[formControlName]=i"[formLabel]='组'+(i + 1)+':'"></app-group-control></ng-容器></ng-容器></ng-容器></表单>
如你所见,有一个 div
包含 ngIf 逻辑:
<div *ngIf="i >0″><div [formGroupName]=i"><输入类型=文本"formControlName=连接器">
这个方法不起作用,但我尝试过的其他方法也没有.
到目前为止,我已经多次尝试将 FormGroupName 更改为 groups
、statements
、i
、index
,导致没有改善.
我还尝试使用 @ViewChildren('templateRef') templateRefVar: QueryList;
跟踪 AppComponent 中每个 ngFor
的实例,然后在 ngFor
,使用模板引用 #templateRef
.从那里,我使用 @Input() groupInstances
将此 templateRef.length
传递给我的子组件 GroupControlComponent
,然后使用里面的 ngIf .这是我得到的最接近的,但问题是,每次满足 ngIf 条件时,它都会出现在组数组的每个实例上,包括第一个,并给我错误:ExpressionChangedAfterItHasBeenCheckedError: Expression查了之后就变了.以前的值:'0'.当前值:'1'.
.这是我使用此方法获得的最接近的 StackBlitz.而这里是来自上述代码的StackBlitz.
如果您想了解有关此递归形式的更多信息,可以在此处阅读有关内容.
解决方案
Stackblitz 演示
让我们将 groupInstance
替换为 showConjunctor
只是为了更清楚地了解它的用途.
您可以在app.component.hml
中执行此操作:
</app-group-control>
我认为上面代码片段中的 i
是 *ngFor
中当前循环的索引(就像在 Stackblitz 演示中一样).
另外,从 app.component.html
中删除这部分:
<div *ngIf="i >0″><div [formGroupName]=i"><输入类型=文本"formControlName=连接器">
[更新]:根据您的评论,如果您想在所有在嵌套组中,您可以在 GroupControlComponent
中将 @Input() showConjuntor
设置为 true (Stackblitz 演示):
<app-group-control *ngFor="let s of _groupsFormArray?.controls;索引为 i"(remove)=_deleteGroupFromArray(i)";[formControlName]=i"[formLabel]='嵌套组'+ (i + 1) + ':'";[showConjunctor]=真"></app-group-control></ng-容器>
Here is the stackblitz for the code below.
I am making a fairly complex deeply nested Angular form using FormArrays, and child components. For the most part, everything is working as expected. A group
object contains a conjunctor
, conditions[]
, and groups[]
. groups[]
is a nested group that can be nested infinitely containing the same object.
Currently, you have the option to "add group", "add nested group", "add condition", "delete group", and "delete condition" so that it makes a nested form object. To do this, the app is split into 3 components:
AppComponent: Holds the main form with ng-container
s and *ngFor
to iterate over the groups
GroupControlComponent: Holds the logic of each item inside the AppComponent and does the same thing as the AppComponent but for Conditions and Nested Groups
ConditionsForm: Holds the logic of the conditions items
And there is an ActionsButtonsBarComponent to hold the buttons to emit events, add, and remove the groups and conditions.
I am trying to make it so on every second group, there is an input for the Conjunctor. I don't want it at all on the first instance since I want the first to always be null. However, on the 2nd and thereafter instances, I want the conjunctor input to appear giving the option to be either "AND" or "OR". As I create this, I am getting the error: ERROR: Cannot find control with path: 'statement → groups → 1 → conjunctor
coming from the AppComponent.
Here's how the AppComponent looks:
<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>
As you can see, there is a div
containing the ngIf logic:
<div *ngIf="i > 0">
<div [formGroupName]="i">
<input type="text" formControlName="conjunctor">
</div>
</div>
This method is not working, but neither have the other methods I have tried.
So far, I have tried changing the FormGroupName many times to groups
, statements
, i
, index
, resulting in no improvement.
I have also tried tracking the instances of each ngFor
from the AppComponent using @ViewChildren('templateRef') templateRefVar: QueryList<ElementRef>;
and then inside the ngFor
, using a template ref #templateRef
. From there, I pass this templateRef.length
to my child component GroupControlComponent
using @Input() groupInstances
, and then using the ngIf inside. This is the closest I have gotten, but the problem is, every single time the ngIf condition is met, it appears on EVERY instance of the group arrays, including the first, as well as gives me the error: 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 from the code as of above.
If you'd like to find more about this recursive form, you can read about that here.
解决方案
Stackblitz demo
Let's replace groupInstance
for showConjunctor
just to make it more obvious about what it's there for.
You can do this in you app.component.hml
:
<app-group-control
#templateRef
(remove)="_delete(i)"
[formControlName]="i"
[formLabel]="'Group '+ (i + 1) + ':'"
[showConjunctor]="!((i + 1) % 2)">
</app-group-control>
I'm considering that i
, in the above snippet, is the index of the current loop in *ngFor
(like in the Stackblitz demo).
Also, remove this part from the app.component.html
:
<div *ngIf="i > 0">
<div [formGroupName]="i">
<input type="text" formControlName="conjunctor">
</div>
</div>
[UPDATE]: Per your comments, if you want to have the conjunctor in all
of the nested Groups, you can set the @Input() showConjuntor
to true inside the GroupControlComponent
(Stackblitz demo):
<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>
这篇关于无法在递归角形式上使用 ngIf 找到带路径的控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文