Reputation: 25377
I am having a nested operation in order to first remove an offer and then save it again as a repeating one.
The problem is, that after saving the repeating offer, I want to patchValue()
the item in offerList[index]
. This is where I am getting the error:
Error: Must supply a value for form control with name: 'id'.
Debugging however revealed that everything should be fine. The object saved
in the final subscription has valid fields set. id
is present and not null:
this._offerService.remove(this.placeId, offer)
.pipe(
flatMap((removed: OfferModel) => {
// Re-use the removed offer to save a repeating one
removed.id = null;
removed.repeatWeekly = true;
return this._offerService.save(this.placeId, removed)
.pipe(finalize(() => this.updateOffersFormArray()));
}),
)
.subscribe(
(saved) => {
console.log(saved);
// offerList is either this.offers or this.repeatingOffers
offerList[index].patchValue(saved);
});
The console will log:
{id: 55, offerDate: "2019-03-04", …}
This is what happens in updateOffersFormArray()
:
// this.offersFormArray is a FormArray
updateOffersFormArray() {
const tmp = this.repeatingOffers.concat(this.offers);
console.log(tmp);
this.offersFormArray.setValue(tmp); // <-- Throws error
}
The console ouput shows me an array of FormGroup
elements, as expected, and each value
of those FormGroup
elements has an offer which has all the values set - especially id
- which is according to the error message not set.
I'm scratching my head over this for quite some time now and I just don't see it.
I know the code looks a bit weird. After updateOffersFormArray()
gets executed, the status change event of this.offersFormArray
will update this.offers
and this.repeatingOffers
which I need for displaying purposes. Just to complete the picture, here is the code which does that:
this.offersFormArray.statusChanges.subscribe((e) => {
const offers: Array<AbstractControl> = [];
const repeatingOffers: Array<AbstractControl> = [];
for (const k of Object.keys(this.offersFormArray.controls)) {
const offerForm = this.offersFormArray.controls[k];
const offer = <OfferModel> offerForm.value;
if (offer.repeatWeekly) {
repeatingOffers.push(offerForm);
} else {
offers.push(offerForm);
}
}
this.offers = offers;
this.repeatingOffers = repeatingOffers;
});
Upvotes: 1
Views: 8124
Reputation: 25377
Turns out I was mistaken about setValue()
of the FormArray
. It does not accept a list of AbstractControl
but instead it requires the values which match the structure of the control.
All I had to do was change
this.offersFormArray.setValue(tmp);
to
this.offersFormArray.setValue(tmp.map(control => control.value));
Upvotes: 1