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.