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:
- Find a way to make this work after all
- Pass down the additional
FormGrouptoOfferItemComponentand try to make it work like that
Any 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) {
// ..
}
}
#someForm="ngForm", I have not tried with Reactive forms