Reputation: 119
I'm working on an application built with Angular and NgRx.
I have a reactive form and I need to set the default values for one form control using the data from the store.
export class FormComponent implements OnInit {
networks: Network[];
form: FormGroup;
ngOnInit(): void {
this.form = this.fb.group({
selectedNetworks: ['', [Validators.required]],
...
});
this.store.select(selectNetworks).subscribe(networks => {
this.networks = networks;
this.form.get('selectedNetworks').setValue(networks);
});
}
<mat-select
formControlName="selectedNetworks"
multiple>
<mat-option
*ngFor="let n of networks"
[value]="n">
{{n.name}}
</mat-option>
</mat-select>
As you can see, I have a multiselect which contains a list of networks. Initially, all the networks should be selected.
In order to get all the required networks, I need to make several http requests (these are the requirements, they cannot be changed). After each successful request, the ngrx store will update and the selectNetworks selector will emit a new value. In case I need to make 2 requests to get the networks, the selector will return all the networks only after the second emission.
There is also a websocket event which returns a network in case it was updated (the status was changed for example). In that case, the ngrx store will be updated and the selectNetworks selector will emit again.
My problem is in the following case: the form is initialised (all the networks are selected), the user makes it so that only one network is selected, the websocket event is fired, the selectNetworks subscription is executed and all the networks are selected yet again, discarding the changes made by the user.
I've done some research and I've saw some solutions where take(1) is being used. However this doesn't work in my case because the first emission might not contain the full list of networks. Do you know if there is a solution which can be applied for my case?
Thanks in advance!
Upvotes: 0
Views: 1558
Reputation: 3163
Judging by the code I can see you are overwriting the control's value with the state from the store which once again selects everything.
There are couple of options what to do here but basically you should assign the whole array to control's value only if there is no value already (nothing is selected). If there is something selected, then reuse it when there is an update from Store.
// update network array declaration
networks: Network[] = [];
this.store.select(selectNetworks).subscribe(networks => {
this.networks = networks;
const selected = this.form.get('selectedNetworks').getValue();
const controlValue = selected.length > 0 ? selected : networks;
// or !!selected, not exactly sure what will getValue() return
this.form.get('selectedNetworks').setValue(controlValue);
});
Upvotes: 1