Reputation: 1034
I have a Business Object Car{id:2,name:ford,modelNo:123}
I also have a MetaData class for CarMetaData{columnName:string,type:text,required:true}
each attribute has it's own CarMetaData object
how can I display Car
data in a form in such a way using an Array of CarMetaData objects
In the template.html file
<form #carForm='ngForm'>
<div class="form-group" *ngFor="let metaData of metadata" >
<input [(ngModel)]="car[metaData.columnName]" name="metaData.columnName"
type="text">
</div>
</form>
In the component file
car:Car;
metadata:CarMetaData[];
The above method isn't working because of the [] in car[meta.columnName] in the ngModel is there a way an expression can be worked out in *ngFor or [(ngModle)] to calculate columName
Upvotes: 3
Views: 3367
Reputation: 11000
Very stupid mistake. Please try this:
<div *ngFor="let meta of metaData;">
<input [(ngModel)]="car[meta.columnName]" name="{{meta.columnName}}" />
{{meta.columnName}}
</div>
But first - your loop (meta in metaData
) is wrong as you loop array, not object. So you better do let meta of metaData, let i = index
.
And the interesting part is how ngModel
sets the value of inputs in ngFor
. If you try this:
<div *ngFor="let meta of metaData; let i = index">
<input [(ngModel)]="car[meta.columnName]" name="meta.columnName" />
{{meta.columnName}}
</div>
You will see that input value is the same of all inputs (it was picked from the first ngFor iteration and repeated to all inputs). However, {{meta.columnName}}
prints correct values. So there is some scoping issue. Other strange thing - its definitely related with ngForm
and input's name
property. If you move that outside of the form - all happens as expected. And if you:
<div *ngFor="let meta of metaData; let i = index">
<input [(ngModel)]="car[meta.columnName]" name="{{metaData[i].columnName}}" />
{{meta.columnName}}
</div>
Inside the form - again, all works well. So that might be your workaround.
Here is a DEMO. Hopefully someone will explain it further.
Upvotes: 1
Reputation:
I'd suggest to put both objects in a wrapper-object. e.g.
export class CarWrapper {
constructor(
car: Car,
carMetaData: CarMetaData
) {}
}
Then build a method that joins both objects in this wrapper
private carWrapper: Array<CarWrapper> = [];
private fillCarWrapper(): void {
// your code here
}
And in your template you act like this
<form #carForm='ngForm'>
<div class="form-group" *ngFor="let wrapper of carWrapper">
<input [(ngModel)]="wrapper.car" name="wrapper.carMetaData.columName" type="text">
</div>
</form>
Upvotes: 1