There can be many different approaches to go about doing this. I'll just share two approaches at the moment and if you feel any of these approaches don't satisfy your use case, we can consider a different approach(provided that you give more information on what exactly you're trying to achieve here).
Approach 1:
You have two properties on your Component:
form$: Observable<FormGroup>;
list: Array<Element>;
Once you have the API response, instead of subscribe
ing to it, you map
it and generate a form while also assigning the value of the response to the list
property that you've declared. Something like this:
this.form$ = this.service.getElements()
.pipe(
map((list: Array<Element>) => {
this.list = list;
return this.fb.group({
elementId: [list[0].id],
elementDescription: [list[0].description]
});
})
);
And then you use it in the template, somewhat like this:
<form
*ngIf="form$ | async as form"
[formGroup]="form">
<label for="">Element Id: </label>
<select formControlName="elementId">
<option
*ngFor="let element of list"
[value]="element.id">
{{ element.id }}
</option>
</select>
<br>
<label for="">Element description: </label>
<select formControlName="elementDescription">
<option
*ngFor="let element of list"
[value]="element.description">
{{ element.description }}
</option>
</select>
</form>
Approach 2:
You might want to club both the list and the FormGroup
together. So you can create a single property in your Component:
elementListWithForm$: Observable<{ list: Array<Element>, form: FormGroup }>;
You'd then assign a value like this:
this.elementListWithForm$ = this.service.getElements()
.pipe(
map((list: Array<Element>) => ({
form: this.fb.group({
elementId: [list[0].id],
elementDescription: [list[0].description]
}),
list,
}))
);
And then you can use it in the template like this:
<form
*ngIf="(elementListWithForm$ | async) as formWithList"
[formGroup]="formWithList.form">
<label for="">Element Id: </label>
<select formControlName="elementId">
<option
*ngFor="let element of formWithList.list"
[value]="element.id">
{{ element.id }}
</option>
</select>
<br>
<label for="">Element description: </label>
<select formControlName="elementDescription">
<option
*ngFor="let element of formWithList.list"
[value]="element.description">
{{ element.description }}
</option>
</select>
</form>
Here's a Working Code Sample on StackBlitz for your ref.
PS: This approach is heavily inspired by the one I used in an article that I wrote about increasing the performance of a deeply nested reactive form in Angular for AngularInDepth. You might want to check that out as well.
Hope this helps. :)