Reputation: 25397
I am having a calendar which is essentially represents a huge form. At the moment there is not a lot to see but what for now it gets a list of dates
from which I start to build up a form:
this.dates.forEach(d => {
group[d] = this._formBuilder.group({
offers: this._formBuilder.array([])
});
});
So, what I actually want is this: A map from date to a list of items
{
'2018-01-01': [{id: 1}, {id: 2}],
'2018-01-02': [{id: 5}, {id: 9}]
}
However, following this tutorial it seems I am currently ending up with something like:
{
'2018-01-01': {offers: [{id: 1}, {id: 2}]},
'2018-01-02': {offers: [{id: 5}, {id: 9}]}
}
which is good enough for me - I just want this to work.
I am passing down the offers
form group in the parent component:
<form [formGroup]="form" *ngIf="form != null">
<div fxLayout="row" >
<app-calendar-day *ngFor="let date of dates$ | async"
[formGroup]="form.get(date)">
</app-calendar-day>
</div>
</form>
This is working so far.
My problems start at the final step where I want to add offers/items to the FormArray
.
<div [formGroup]="formGroup">
<mat-card *ngFor="let offer of formGroup.get('offers').controls; let idx = index" style="margin: 4px; padding: 10px;">
<app-offer-item [formGroupName]="idx">
</app-offer-item>
</mat-card>
</div>
The calendar allows to add items/offers and I want formGroup.get('offers')
(the FormArray
) to be built up dynamically s.t. I can post the entire thing at the end ot the day.
However, I do not know how to bind the offer/item correctly.
The app-offer-item
is built on AbstractControlComponent
which delivers ControlValueAccessor
and Validator
interfaces as well as some default implementations. The code for OfferItemComponent
aka app-offer-item
is below. Since it encapsulates an object, I am quite certain that this element should represent a FormGroup
but I am not able to wire the pieces together correctly as it seems.
The code above is giving me
ERROR Error: Cannot find control with unspecified name attribute
This seems to happen right after I add an item/offer to the FormArray
:
onAddOffer(offer) {
const formArray = <FormArray> this.formGroup.get('offers');
formArray.push(this._formBuilder.group(offer));
// ..
}
I expected writeValue()
in OfferItemComponent
to be called somehow but I guess that's not how it works.
I think I have two options here:
FormGroup
to OfferItemComponent
and try to make it work like thatAny help is very much appreciated!
OfferItemComponent
@Component({
selector: 'app-offer-item',
styles: [`
`],
template: `
<div>
<div [innerHTML]="getItemHtml()"></div>
<div>
<span style="padding-right: 4px;">€</span>
<mat-form-field style="text-align: right; width: 55px; margin-bottom: -1.25em;">
<input matInput autocomplete="off" (focusout)="formatPrice($event.target)"/>
</mat-form-field>
</div>
</div>
`,
providers: [
DecimalPipe,
ValueAccessorProvider(OfferItemComponent),
ValidatorsProvider(OfferItemComponent)
]
})
export class OfferItemComponent extends AbstractControlComponent {
@Input()
items;
offer: OfferModel;
constructor(
@Inject(LOCALE_ID) public locale: string,
private _decimalPipe: DecimalPipe
) {
super();
}
writeValue(offer: OfferModel): void {
this.offer = offer;
this._onChangeCallback(this.offer);
}
validate(c: AbstractControl): ValidationErrors | any {
// ..
}
getItemHtml() {
// ..
}
formatPrice(element) {
// ..
}
}
Upvotes: 0
Views: 681
Reputation: 3149
I believe that all of your form control elements within a [formGroup] need to have the "name" and the "formControlName" attribute set as well.
[attr.data-name]="name_of_field" [formControlName]="name_of_field"
Upvotes: 1
Reputation: 11243
The missing element in your code is
formArrayName
<div formArrayName="offers">
<mat-card *ngFor="let offer of formGroup.get('offers').controls; let idx = index" style="margin: 4px; padding: 10px;">
<app-offer-item [formGroupName]="idx">
</app-offer-item>
</mat-card>
</div>
Upvotes: 0