Luckily Angular with its expressiveness allows us develop a solution. Let's create component that takes array of controls and build the form.
@Component({ selector: 'app-root', template: `<div style="margin: 50px"> <declarative-form [controls]="controls" (submitMe)="onSubmit($event)"></declarative-form> </div>` }) export class AppComponent { controls: Object[] = [ {name: 'name', label: 'Yout name', type: 'text'}, {name: 'name2nd', label: 'Your second name', type: 'text'}, new Control('name3rd', 'Your third name'), {name : 'description', label: 'Descrition', type: 'textarea' }, new Control('age', 'Your age', 'range'), new Control('mobile', 'Mobile number'), new Control('gender', 'Gender', 'radio', {'options' : ['Male', 'Female']}), new Control('favFood', 'Favourite Food', 'radio', {'options' : ['Pasta', 'Pizza', 'Hamburgers', 'Soups', 'Chinese']}), new Control('country', 'Country', 'dropdown', {'options': ['US','PL', 'DE']}), ] onSubmit(values) { console.log(values); } }Ok, let's start with creating declarative-form component
@Component ({ selector: 'declarative-form', template: `<form [formGroup]="form" novalidate> <my-form-input *ngFor="let control of controls" name="{{control.name}}" label="{{control.label}}" type="{{control.type}}" [params]="control.params" [form]="form"></my-form-input> <button type="submit" (click)="onSubmit()">Submit me</button> </form> <pre>{{form.value | json}}</pre>` }) export class DeclarativeFormComponent{ @Input() controls: Control[]; @Output() submitMe = new EventEmitterThe(); form: FormGroup; constructor(private formBuilder: FormBuilder) { } ngOnInit(){ let cfg = new Object(); this.controls.forEach(c => cfg[c.name] = ''); this.form = this.formBuilder.group(cfg); } onSubmit(){ console.log(this.form.value); this.submitMe.emit(this.form.value); } }
ngOnInit
function is most tricky here. What it does is creating configuration object for the form builder
.
The last missing piece is my-form-input
component - your homework ;)