I'm trying to create dynamic from groups based on initial data with filled content and add/remove from groups. Unfortunately it is not working.
Expected behavior is,
- Coutry dropdown would be loaded with data and highlighted with selected value which is working fine already.
- Selected country states dropdown data should be loaded by default with selected value from initial data
stateCode
and when changing the country too which is not working currently. - While clicking the add button, by default "United states" country and respective states data should be loaded. States dropdown should be selected by default with "--select--".
Note: All data will be coming from API. Testing purpose I have added static objects for Countries and States.
Here my attempt
https://stackblitz.com/edit/angular-8-app-example-fkjzfe-wekubn?file=src%2Fapp%2Fapp.component.ts
Current behaviour demo
https://angular-8-app-example-fkjzfe.stackblitz.io/
HTML
<form [formGroup]='entityForm'>
<div formArrayName="optionGroups" class="ui-g ui-g-12 ui-g-nopad " >
<div style="width: 100%;
display: flex; margin-bottom:10px" class="ui-g ui-g-12 ui-g-nopad " *ngFor="let item of entityForm.controls['optionGroups'].controls; let $index=index" [formGroup]="item">
<div class="ui-md-4">
<label class="mandatory"
>Country
<span class="colon"></span>
</label>
<select formControlName="country" class="ui-inputtext" (change)="onCountryChange(entityForm.controls['optionGroups'].controls[$index].controls['country'].value, $index)" >
<option>--Select--</option>
<option *ngFor="let c of countries" [ngValue]="c.countryCode">{{c.country}}</option>
</select>
</div>
<div class="ui-md-4">
<label class="lbl-hidden"> State </label>
<select formControlName="state" class="ui-inputtext">
<option>--Select--</option>
<option *ngFor="let state of states[entityForm.controls['optionGroups'].controls[$index].controls['country'].value]" value="state.code">{{state.state}}</option>
</select>
</div>
<div class="ui-md-3">
<label class="lbl-hidden"> Number </label>
<input
type="text"
pInputText
class="form-control"
formControlName="place"
/>
</div>
<div class="ui-md-1">
<button (click)='removeOptionGroup(i)' style="min-width: auto;" pButton icon="fa fa-minus">Remove</button>
</div>
</div>
</div>
</form>
<button class="add-remove-btn" pButton (click)='addOptionGroup()' icon="fa fa-plus">Add</button>`
TS
import { Component, OnInit, ViewChild } from '@angular/core'
import { FormBuilder, Validators, FormArray, FormGroup, FormControl } from '@angular/forms';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
public countryOptions:any = [];
public stateOptions:any = [];
public countries = [];
public states = [];
public entityForm: FormGroup;
constructor(private fb: FormBuilder) {
this.entityForm = this.fb.group({
optionGroups : this.fb.array([]),
});
this.countries = this.countryOptions
this.states=[];
}
public addOptionGroup(){
const fa = this.entityForm.controls["optionGroups"] as FormArray;
//fa.setValue("--Select--");
fa.push(this.newOptionGroup());
}
public removeOptionGroup(index: number){
const fa = this.entityForm.controls["optionGroups"] as FormArray;
fa.removeAt(index);
}
onCountryChange(selectedCountry: string , formIndex : number) : void {
this.states[selectedCountry] = this.getStates(selectedCountry)
}
private newOptionGroup() {
return new FormGroup({
country: new FormControl("--select--"),
state: new FormControl("--select--"),
place: new FormControl("GGG"),
});
}
getStates(selectedCountry) {
//API call
switch(selectedCountry) {
case "US" :
this.stateOptions =[
{id: 14, state: "Alabama", code: "AL", countryCode: "US"},
{id: 15, state: "Alaska", code: "AK", countryCode: "US"},
{id: 17, state: "Arizona", code: "AZ", countryCode: "US"},
{id: 18, state: "Arkansas", code: "AR", countryCode: "US"},
{id: 19, state: "California", code: "CA", countryCode: "US"}
]
break;
case "CA" :
this.stateOptions =[{id: 37, state: "Marshall Islands", code: "MH", countryCode: "CA"},
{id: 4, state: "New Brunswick", code: "NB", countryCode: "CA"},
{id: 5, state: "Newfoundland and Labrador", code: "NL", countryCode: "CA"},
{id: 53, state: "Northern Mariana Islands", code: "MP", countryCode: "CA"},
{id: 6, state: "Northwest Territories", code: "NT", countryCode: "CA"}]
break;
default:
this.stateOptions =[
{id: 14, state: "Alabama", code: "AL", countryCode: "US"},
{id: 15, state: "Alaska", code: "AK", countryCode: "US"},
{id: 17, state: "Arizona", code: "AZ", countryCode: "US"},
{id: 18, state: "Arkansas", code: "AR", countryCode: "US"},
{id: 19, state: "California", code: "CA", countryCode: "US"}
]
break;
}
return this.stateOptions;
}
initFormArray(initForm:any) {
const formArray = this.entityForm.get('optionGroups') as FormArray;
initForm.map((item, index) => {
formArray.push(this.createForms(item, index));
});
this.entityForm.setControl('optionGroups', formArray);
}
createForms(adresse, index): FormGroup {
let formGroup: FormGroup = new FormGroup(
{
country: new FormControl(adresse.countryCode),
state: new FormControl(adresse.stateCode),
place: new FormControl(adresse.fileNumber)
}
);
this.onCountryChange(adresse.select1, index)
return formGroup;
}
getAllCountries() {
//API call
this.countries = [{"country":"United States","countryCode":"US"},{"country":"Canada","countryCode":"CA"}]
}
ngOnInit() {
this.getAllCountries()
const initData = [
{countryCode: "US", stateCode: "AZ", fileNumber: "AAA"},
{countryCode: "CA", stateCode: null, fileNumber: null}
]
this.initFormArray(initData)
}
}
I symplified you scripts and seems work as due. But it's not finish - all may be done much more pretty. Pay attention to the formation html part - [formGroupName]="i" and how to work with formArray variable.