无法在递归角形式上使用 ngIf 找到带路径的控件 [英] Cannot Find Control with Path Using ngIf on Recursive Angular Form

查看:22
本文介绍了无法在递归角形式上使用 ngIf 找到带路径的控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

AppComponent:使用 ng-containers 和 *ngFor 保存主表单以遍历组

GroupControlComponent:在 AppComponent 中保存每一项的逻辑,并与 AppComponent 做同样的事情,但对于条件和嵌套组

ConditionsForm:保存条件项的逻辑

还有一个 ActionsButtonsBarComponent 来保存按钮以发出事件、添加和删除组和条件.

我试图让每组都如此,Conjunctor 有一个输入.我在第一个实例上根本不想要它,因为我希望第一个始终为空.但是,在第 2 次及之后的实例中,我希望出现连接器输入,并提供AND"和AND"选项.或或".当我创建这个时,我收到错误:ERROR:找不到路径控制:'statement → groups → 1 → conjunctor来自 AppComponent.

AppComponent 的外观如下:

<ng-container formGroupName="statement"><ng-container formArrayName="groups"><ng-container *ngFor="let group of _groupsFormArray?.controls;索引为 i"><div *ngIf="i >0″><div [formGroupName]=i"><输入类型=文本"formControlName=连接器">

<应用组控制(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 更改为 groupsstatementsiindex,导致没有改善.

我还尝试使用 @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-containers 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屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆