Issue
Consider the following formArray excerpt inside the template:
<div class="p-col-12 controls-div" formArrayName="fields">
<div
class="p-grid"
*ngFor="let item of getFieldControls(); let i = index"
[formGroupName]="i"
style="margin-top: 10px;">
<div class="p-col-8">
<!-- if string is Text -->
<input
*ngIf="string == 'Text'"
type="text"
pInputText
formControlName="control">
<!-- if string is number -->
<input
*ngIf="string == 'Number'"
type="text"
pInputText
formControlName="control">
<!-- if string is Yes/No -->
<p-toggleButton
*ngIf="string == 'Yes/No'"
onLabel="Yes"
offLabel="No"
formControlName="control"></p-toggleButton>
</div>
<div class="p-col-2">
<button
type="button"
class="btn btn-danger"
(click)="onDeleteField(i)">X</button>
</div>
</div>
</div>
I want to pass down a string from my getFieldControls() method and bind to the control, in the *ngFor loop, to the correct "type of control" (element). My problem is I tried a 100 different ways to pass this string. I tried adding a data-type attribute like so:
(<FormArray>this.itemForm.get('fields')).push(
new FormGroup({
'control': new FormControl(
{data-type: 'number', value:variable.name, disabled:true}, [Validators.required])
})
);
I then wanted to read it, in template, like so:
*ngIf="item[0].control.data-type == 'text'"
but the compiler complained. It seems that I can only pass down value and disabled. Later on I tried setting a value to the formgroup, also no luck. If I can pass a string I would know which control to load into the DOM in the template. I also tried to add the element directly, dynamically, from typescript like so:
<div [innerHTML]="elementToAdd"></div>
and in typescript
if (this.type == 'number') {
elementToAdd += '<input type="number" ...>';
}
When I did this, every time a add a control the I added like 4 or 8 controls. At the end of the day I would get a, lets say ‘dropdown’, value (string) in the template and *ngIf only the dropdown and then bind to it.
I use an array to find, based on an id, which type of control to load. My method to push a new control looks like so:
onAddField(id: string) {
let variable = this.variables.find(i => i.id === id);
if (variable?.control == 'Text') {
//add an Input
(<FormArray>this.itemForm.get('fields')).push(
new FormGroup({
'control': new FormControl(
{value:variable.name, disabled:true}, Validators.required)
})
);
}
if (variable?.control == 'Number') {
//add an Input
(<FormArray>this.itemForm.get('fields')).push(
new FormGroup({
'control': new FormControl(
{value:variable.name, disabled:true}, Validators.required)
})
);
}
//somewhere in the formgroup or formcontrol I want to pass a string so that I can know which form control to load, using *ngIf,in the template.
}
I init my form like so:
this.itemForm = new FormGroup({
fields: new FormArray([])
});
And to get the controls, here is my method:
getFieldControls() {
let controls = (this.itemForm.get('fields') as FormArray).controls;
return controls;
}
Solution
you can do it that way.
<div class="p-col-12 controls-div" formArrayName="fields">
<div
class="p-grid"
*ngFor="let item of getFieldControls(); let i = index"
[formGroupName]="i"
style="margin-top: 10px;">
<div class="p-col-8">
<!-- if string is Text -->
<input
*ngIf="typeList[index] == 'Text'"
type="text"
pInputText
formControlName="control">
<!-- if string is number -->
<input
*ngIf="typeList[index] == 'Number'"
type="text"
pInputText
formControlName="control">
<!-- if string is Yes/No -->
<p-toggleButton
*ngIf="typeList[index] == 'Yes/No'"
onLabel="Yes"
offLabel="No"
formControlName="control"></p-toggleButton>
</div>
<div class="p-col-2">
<button
type="button"
class="btn btn-danger"
(click)="onDeleteField(i)">X</button>
</div>
</div>
</div>
and in onAddField()
you can do it as. because I think variable
is somewhat relevant here.
typeList: stringp[] = [];
onAddField(id: string) {
let variable = this.variables.find(i => i.id === id);
this.typeList.push(variable?.control)
if (variable?.control == 'Text') {
//add an Input
(<FormArray>this.itemForm.get('fields')).push(
new FormGroup({
'control': new FormControl(
{value:variable.name, disabled:true}, Validators.required)
})
);
}
if (variable?.control == 'Number') {
//add an Input
(<FormArray>this.itemForm.get('fields')).push(
new FormGroup({
'control': new FormControl(
{value:variable.name, disabled:true}, Validators.required)
})
);
}
//somewhere in the formgroup or formcontrol I want to pass a string so that I can know which form control to load, using *ngIf,in the template.
}