angular - 无法在递归角度表单上使用 ngIf 找到带有路径的控件
问题描述
这是下面代码的堆栈闪电战。我正在使用 FormArrays 和子组件制作一个相当复杂的深度嵌套的 Angular 表单。在大多数情况下,一切都按预期工作。group
对象包含conjunctor
、conditions[]
和groups[]
。groups[]
是一个嵌套组,可以无限嵌套包含相同的对象。
目前,您可以选择“添加组”、“添加嵌套组”、“添加条件”、“删除组”和“删除条件”,以便创建嵌套表单对象。为此,应用程序分为 3 个组件:
ng-container
AppComponent:用s保存主窗体并*ngFor
遍历组
GroupControlComponent:保存 AppComponent 中每个项目的逻辑,并与 AppComponent 执行相同的操作,但用于条件和嵌套组
条件表单:保存条件项的逻辑
还有一个 ActionsButtonsBarComponent 来保存按钮以发出事件、添加和删除组和条件。
我试图在每第二组中做到这一点,Conjunctor 有一个输入。我根本不希望它在第一个实例上,因为我希望第一个始终为空。但是,在第 2 次及之后的实例中,我希望连接器输入出现,提供“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
,但没有任何改善。
我还尝试使用模板 ref跟踪ngFor
AppComponent中的每个实例,@ViewChildren('templateRef') templateRefVar: QueryList<ElementRef>;
然后在ref 中跟踪每个实例。从那里,我使用 ngIf 将其传递给我的子组件,然后使用内部的 ngIf 。这是我得到的最接近的,但问题是,每次满足 ngIf 条件时,它都会出现在组数组的每个实例上,包括第一个实例,并给我错误:。这是我使用此方法获得的最接近的 StackBlitz。这是上面代码中的 StackBlitz。ngFor
#templateRef
templateRef.length
GroupControlComponent
@Input() groupInstances
ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: '0'. Current value: '1'.
如果您想了解有关此递归形式的更多信息,可以在此处阅读。
解决方案
让我们替换groupInstance
forshowConjunctor
只是为了更清楚地了解它的用途。
你可以这样做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>
[更新]:根据您的评论,如果您想在所有嵌套组中使用连接器,您可以在(Stackblitz 演示@Input() showConjuntor
)中将其设置为 true :GroupControlComponent
<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>
推荐阅读
- maven - Maven (Tycho) 无法解析 OSGi 核心包
- javascript - 为什么在这段代码中,箭头函数的外部作用域是 `showList` 而不是 `forEach`?
- joomla2.5 - 如何为 k2 类别创建自定义模板并将此模板分配给 Joomla 支持?
- python - 欧几里得距离的迭代计算
- python - 为什么我在递归函数中的 list.append() 总是添加到 Python 的顶层
- php - 在 wp_postmeta 中更新/插入 meta_key 和 meta_value
- html - 关键帧动画在不可见时是否也会渲染?它们是否消耗资源?
- mysql - 计算消息接收响应所用的时间 (SQL)
- javascript - 如何访问从 Promise.all() 返回的密钥
- javascript - Safari ios 13:跨源 iframe 上的 DeviceOrientationEvent.requestPermission()