There is a form with filters. I create the form through FormBuilder. There are no problems with static data, but I cannot cope with incoming data. I need to render a group of checkboxes in airlines, similar to transferFilter. With the help of pathValue I change the value of the field to the processed data, 10 elements come out. In
{{filtersForm.value | json}}, the data is displayed and changed, well, checkboxes do not appear. I don’t want to split the form into separate entities, but if I don’t find the answer, I’ll have to redo it.
Method for forming a group of checkboxes:
private mapToCheckboxArrayGroup (data: string [], display): FormArray {
return this.fb.array (
data.map ((val, i) => {
return this.fb.group ({
value: val,
display: display [i],
selected: false,
});
})
);
}
I create a group:
filtersForm: FormGroup = this.fb.group ({
sort: [this.priceSortItems [0] .attribute],
transferFilter: this.mapToCheckboxArrayGroup (
this.availableTransferValue,
this.availableTransferDisplay
),
minCost: [null],
maxCost: [null],
airlines: [null],
});
I receive data, process it and form a group using the method:
private refresh $ = new Subject ();
carriers $ = this.refresh $ .pipe (
startWith (true),
switchMap (() => this.dataService.getCarriers ()),
map ((e) => {
const keys = [... Object.keys (e)];
const values = [... Object.values (e)];
const airItems = this.mapToCheckboxArrayGroup (keys, values);
return airItems;
}),
shareReplay (1)
);
I react to changes in the form:
filterData $ = this.refresh $ .pipe (
startWith (this.filtersForm.value),
switchMap (() => this.filtersForm.valueChanges),
map ((e) => {
console.log (e);
console.log (this.filtersForm.controls);
}),
shareReplay (1)
);
I subscribe to the data update and through PathValue change the value of the airlines group to formarray from the method:
ngOnInit (): void {
this.carriers $ .pipe (takeUntil (this.destroy $)). subscribe ((e) => {
this.filtersForm.patchValue ({
airlines: e.value,
});
});
}
I send an array with data to template via getter:
get carrierFilterArray () {
const carriers = this.filtersForm.get ('airlines') as FormArray;
console.log (carriers.value);
return carriers;
}
HTML Form:
<form * ngIf = "filtersForm.value" [formGroup] = "filtersForm" class = "page__menu menu-page">
<div class = "menu-page__sort" * ngIf = 'priceSortItems'>
<h3 class = "menu-title"> Sort </h3>
<div class = "menu-page__sort items" * ngFor = "let elem of priceSortItems; let i = index">
<input formControlName = "sort" [value] = "elem.attribute" type = "radio" [id] = "elem.value" /> <label
[for] = "elem.value"> {{elem.display}} </label> <br />
</div>
<div class = "menu-page__filter" formArrayName = "transferFilter">
<h3 class = "menu-title"> Filter </h3>
<div class = "menu-page__filter items" * ngFor = "let elem of transferFilterArray.controls; let i = index"
[formGroup] = "elem">
<input type = "checkbox" [formControl] = "elem.get ('selected')" [value] = "elem.get ('value'). value"
[id] = "elem.get ('value'). value" />
<label [for] = "elem.get ('value'). value"> {{elem.get ('display'). value}} </label> <br />
</div>
</div>
<div class = "menu-page__price">
<h3 class = "menu-title"> Price </h3>
<p>
From
<input formControlName = "minCost" type = "text" />
</p>
<p> Before <input formControlName = "maxCost" type = "text" /> </p>
</div>
<div class = "menu-page__airlines" formArrayName = "airlines">
<h3 class = "menu-title"> Airlines </h3>
<div class = "menu-page__filter items" * ngFor = "let elem of carrierFilterArray.controls; let i = index"
[formGroup] = "elem">
<input type = "checkbox" [formControl] = "elem.get ('selected')" [value] = "elem.get ('value'). value"
[id] = "elem.get ('value'). value" />
<label [for] = "elem.get ('value'). value"> {{elem.get ('display'). value}} </label> <br />
</div>
</div>
<pre> {{filtersForm.value | json}} </pre>
</div>
</form>
As a result, I get all normal filters, except for the last one. Below you can see the json form.value, which contains all the data
I understand what needs to be done asynchronously, but I don't understand how ... The project is educational, at first I made it in pure JS, now I want to finish it in Angular. I would be very grateful for a tip.
You need to wait until the incoming data arrives and then you create the form with the required data's
and put a
<div *ngIf="anyKey">
**//Here you need to render your form**
</div>
After receiving the data you need to generate your form.
anyKey = false;
filtersForm: FormGroup;
constructor(){
this.refresh $ .pipe (
startWith (true),
switchMap (() => this.dataService.getCarriers ()),
map ((e) => {
const keys = [... Object.keys (e)];
const values = [... Object.values (e)];
const airItems = this.mapToCheckboxArrayGroup (keys, values);
//Create your form here and make the key as true
this.filtersForm = this.fb.group ({
sort: [this.priceSortItems [0] .attribute],
transferFilter: this.mapToCheckboxArrayGroup (
this.availableTransferValue,
this.availableTransferDisplay
),
minCost: [null],
maxCost: [null],
airlines: airItems
});
this.anyKey = true;
}),
shareReplay (1)
);
}
i think this will help you for rendering all the controls.