Reputation: 4599
I have form fields and need to add some more different fields when the user clicks on the Add button.If the user clicks on Add button, the new form is opening in a modal window where he can configure the name of the field, type and value). How do i add newly created dynamic elements to existing form.
I have tried using the following code but not adding the newly generated fields.
issuer.html
<dynamic-form [dataObject]="person"></dynamic-form>
<button type="submit" class="btn btn-info" (click)="addbtn();">ADD</button>
issuer.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'issuer-config',
templateUrl: './issuer.html'
})
export class IssuerConfig implements OnInit {
person: any = [];
constructor(
) {
person = {
lcid: {
label: 'LCID:',
value: '',
type: 'text'
}
}
}
//Assume the values coming from modal window
addbtn = function() {
Object.assign(this.person, {
ipa: {
label: 'IP:',
value: '',
type: 'text'
},
});
};
}
dynamicform.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { FormBuilder, FormGroup, FormControl, Validators } from '@angular/forms';
@Component({
selector: 'dynamic-form',
template: `
<form novalidate (ngSubmit)="onSubmit(form.value)" [formGroup]="issuerConfigForm" class="form-horizontal">
<div *ngFor="let prop of objectProps">
<div class="form-group row">
<label [attr.for]="prop" class="col-sm-2 control-label">{{prop.label}}</label>
<div [ngSwitch]="prop.type" class="col-sm-4">
<input *ngSwitchCase="'text'"
[formControlName]="prop.key"
[id]="prop.key" [type]="prop.type" class="form-control">
</div>
</div>
</div>
<button type="submit">Submit</button>
</form>
`
})
export class DynamicFormComponent implements OnInit {
@Input() dataObject;
issuerConfigForm: FormGroup;
objectProps;
constructor() {
}
ngOnInit() {
// remap the API to be suitable for iterating over it
this.objectProps =
Object.keys(this.dataObject)
.map(prop => {
return Object.assign({}, { key: prop }, this.dataObject[prop]);
});
// setup the form
const formGroup = {};
for (let prop of Object.keys(this.dataObject)) {
formGroup[prop] = new FormControl(this.dataObject[prop].value || '');
}
this.issuerConfigForm = new FormGroup(formGroup);
}
onSubmit(form) {
console.log(form);
}
}
Upvotes: 0
Views: 3831
Reputation: 1645
issuer.html
<dynamic-form [objectProps]="objectProps" [formGroup]="issuerConfigForm"></dynamic-form>
<button type="submit" class="btn btn-info" (click)="addbtn();">ADD</button>
issuer.component.ts
export class IssuerConfig {
ngOnInit() {
}
person: any = [];
objectProps=[];
issuerConfigForm:FormGroup;
constructor(
) {
this.person = {
lcid: {
label: 'LCID:',
value: '2',
type: 'text'
}
};
this.generateView();
}
//Assume the values coming from modal window
addbtn = function () {
Object.assign(this.person, {
ipa: {
label: 'IP:',
value: '1',
type: 'text'
},
});
this.generateView();
};
generateView(){
// remap the API to be suitable for iterating over it
this.objectProps =
Object.keys(this.person)
.map(prop => {
return Object.assign({}, { key: prop }, this.person[prop]);
});
// setup the form
const formGroup = {};
for (let prop of Object.keys(this.person)) {
formGroup[prop] = new FormControl(this.person[prop].value || '');
}
this.issuerConfigForm = new FormGroup(formGroup);
}
}
dynamicform.component.ts
@Component({
selector: 'dynamic-form',
template: `
<form novalidate (ngSubmit)="onSubmit(form.value)" [formGroup]="formGroup" class="form-horizontal">
<div *ngFor="let prop of objectProps">
<div class="form-group row">
<label [attr.for]="prop" class="col-sm-2 control-label">{{prop.label}}</label>
<div [ngSwitch]="prop.type" class="col-sm-4">
<input *ngSwitchCase="'text'"
[formControlName]="prop.key"
[id]="prop.key" [type]="prop.type" class="form-control">
</div>
</div>
</div>
<button type="submit">Submit</button>
</form>
`
})
export class DynamicFormComponent implements OnInit {
@Input() formGroup;
@Input() objectProps;
constructor() { }
ngOnInit() {
}
}
Upvotes: 0
Reputation: 297
You can follow my below example to render dynamic form:
export class AppComponent implements OnInit {
fields = {
name: {
type: 'text',
value: 12,
label: 'Name'
}
}
fieldProps = Object.keys(this.fields);
form: FormGroup;
formControls = {};
constructor(private fb: FormBuilder) {
this.fieldProps.forEach(prop => {
this.formControls[prop] = [this.fields[prop].value];
})
this.form = this.fb.group(this.formControls);
this.form.valueChanges.subscribe(v => console.log(v));
}
ngOnInit(): void {
}
}
<form [formGroup]="form">
<div *ngFor="let prop of fieldProps">
<label>{{fields[prop].label}}</label>
<div [ngSwitch]="fields[prop].type">
<input *ngSwitchCase="'text'" [formControlName]="prop">
</div>
</div>
</form>
Finally, you should use @Output
to emit the form.value
to the <issuer component>
. I think we should define the controls structure data
more clearly to easy to understand and rendering.
Upvotes: 1