I have multiple (any number) dropdowns on the form that i need to build dynamically.
All these must have a value selected, so need to apply required validator.
Sample json
[
{
"FeatureCaption": "Style",
"SelectedValue": "shaker",
"FeatureList": [
{
"FeatureId": "CHOOSE",
"FeatureName": "Choose",
"IsSelected": true
},
{
"FeatureId": "shaker",
"FeatureName": "Shaker",
"IsSelected": false
}
]
},
{
"FeatureCaption": "Material",
"SelectedValue": "std",
"FeatureList": [
{
"FeatureId": "CHOOSE",
"FeatureName": "Choose",
"IsSelected": true
},
{
"FeatureId": "std",
"FeatureName": "Standard",
"IsSelected": false
}
]
}
]
These features are available on the form via this.features
Component code to get data and to build form
onInit() {
//init form, so angular will complain about formgroup since template is going first
this.inItForm();
this.dataSubscription = this.projectSubService.getProjectSubConfig(this.subId).subscribe(
res => {
this.features = res.Features;
//push in features
this.pushInFormFeatures();
},
error => {
//do error handling part...
}
);
}
inItForm method
inItForm() {
//will be putting the config as FormArray
let configFeatures = new FormArray([]);
//loop through the features and push into configFeatures FormArray above
//this.features.forEach(i =>
// configFeatures.push(
// new FormGroup({
// 'config': new FormControl({ value: i.SelectedValue, options: i.FeatureList, label: i.FeatureCaption }, Validators.required)
// })
// )
//);
//now create the main FormGroup and add config features to it
this.projectForm = new FormGroup({
'features': configFeatures
});
}
Push in form features method
pushInFormFeatures() {
this.features.forEach(i =>
(<FormArray>this.projectForm.get('features')).push(
new FormGroup({
'config': new FormControl({ value: i.SelectedValue, options: i.FeatureList, label: i.FeatureCaption }, Validators.required)
})
)
);
}
and html
<form [formGroup]="projectForm" (ngSubmit)="onSubmit()">
<div class="form-row">
<div class="col">
<div formArrayName="features">
<div class="form-group form-row" *ngFor="let ic of projectForm.get('features'); let i=index;" [formGroupName]="i">
<div class="col-lg-2 text-right"><label for="{{i}}" class="col-form-label">{{ic.label}} <app-required-star></app-required-star></label></div>
<div class="col-lg-10">
<select class="form-control" id="{{i}}" formControlName="config" [appAutoFocus]="">
<!--<option *ngFor="let op of ic.options" [value]="op.FeatureId">{{op.FeatureName}}</option>-->
</select>
<!--<span class="mwk-validation-error form-text" *ngIf="!projectForm.get('features')[{{i}}].valid && projectForm.get('features')[{{i}}].errors?.required">Required</span>-->
</div>
</div>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary btn-sm">Submit</button>
</form>
I am getting following error
ERROR Error: "Cannot find a differ supporting object '[object Object]'
of type 'object'. NgFor only supports binding to Iterables such as Arrays."
Obviously i am not building the formArray properly including select options.
How can i build some thing like this? I have been looking for an example and haven't been able to find one to use.
Update 1
For now using template driven approach till i figure out how to do above
<form (ngSubmit)="onSubmit(f)" #f="ngForm">
<div class="form-group form-row" *ngFor="let f of features; let i=index;">
<div class="col-lg-2 text-right"><label for="{{f.FeatureId}}" class="col-form-label">{{f.FeatureCaption}} <app-required-star></app-required-star></label></div>
<div class="col-lg-10">
<!--custom-select-->
<select class="form-control" id="{{f.FeatureId}}" name="{{f.FeatureId}}" [appAutoFocus]="i === 0" ngModel required>
<option value="" selected>Choose...</option>
<option *ngFor="let fl of f.FeatureList" [value]="fl.FeatureId" [selected]="fl.IsSelected">{{fl.FeatureName}}</option>
</select>
</div>
</div>
<div class="row mt-2">
<div class="col-lg-2 text-right"> </div>
<div class="col-lg-10">
<button type="submit" class="btn btn-primary btn-sm" [disabled]="!f.valid">Submit</button>
</div>
</div>
</form>