5
\$\begingroup\$

I implements big reactive form on angular5. This form get data from JSON. I use formBuilder and several nested formGroups.

Every field have default value before rendering form. In console output form values after submit form.

CSS design is very simple.

Live demo here.

js:

 formData = {
 'Информация из КХД': {
 Марка: {
 type: 'input',
 value: 'qwerty',
 },
 'Модель': {
 type: 'select',
 value: ['wqeqwewq', 'sadasdasdda', 'xcvxcxcvxcv',],
 selected: 1,
 },
 'Год выпуска': {
 type: 'input',
 value: '',
 },
 },
 'Общая информация': {
 'ПТС': {
 type: 'input',
 value: 'qwerty',
 },
 'Пробег': {
 type: 'select',
 value: ['tgtrgrt', 'fdvdfvdf', 'csdcscsc',],
 selected: 2,
 },
 'Тип кузова': {
 type: 'select',
 value: ['sdv', '544564564', 'yjyujuyj',],
 selected: 0,
 },
 },
 // and more, more, more...
 }
 form: FormGroup;
 constructor(private fb: FormBuilder) { }
 ngOnInit() {
 this.form = this.fb.group(
 this.createForm(Object.keys(this.formData))
 );
 }
 createForm(fields) {
 const result = {};
 fields.forEach(field => {
 const fields = Object.keys(this.formData[field])
 result[field] = this.fb.group(this.createSubForm(field, fields));
 });
 return result;
 }
 createSubForm(field, fields) {
 const result = {};
 fields.forEach(f => {
 let fd = this.formData[field][f];
 if (fd.type === 'select') {
 result[f] = new FormControl(fd.value[fd.selected]);
 } else if (fd.type === 'input') {
 result[f] = new FormControl(fd.value);
 } 
 });
 return result;
 }
 getKeys() {
 return Object.keys(this.form.controls);
 }
 getSubKeys(key) {
 const subControls = this.form.get(key).value;
 return Object.keys(subControls);
 }
 onSubmit() {
 console.log('form submitted', this.form.value);
 }

html:

<form class="form" [formGroup]="form" (ngSubmit)="onSubmit()">
 <div class="key" *ngFor="let key of getKeys()">
 <h1 class="head">{{key}}</h1>
 <div class="subKey" *ngFor="let subKey of getSubKeys(key)" [formGroupName]="key">
 <label>{{subKey}}</label>
 <input type="text" [formControlName]="subKey" *ngIf="formData[key][subKey].type === 'input'">
 <select [formControlName]="subKey" *ngIf="formData[key][subKey].type === 'select'">
 <option 
 *ngFor="let item of formData[key][subKey].value; let i = index" 
 [value]="item">
 {{ item }}
 </option>
 </select>
 </div> 
 </div> 
 <button class="submit" type="submit">Submit</button>
</form>

scss:

.head {
 font-weight: bold;
 text-decoration: underline;
 width: 100%;
 margin-bottom: 20px;
}
.key {
 display: flex;
 flex-wrap: wrap;
 justify-content: space-between;
 align-items: flex-start;
 margin-bottom: 30px;
 .subKey {
 width: 47%;
 display: block;
 margin-bottom: 15px;
 >* {
 width: 100%;
 }
 }
}
200_success
146k22 gold badges190 silver badges478 bronze badges
asked May 20, 2018 at 8:13
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

It's an unusual approach, it's very cryptic and as a result will be a bad maintenance of the code in the future, if in the future you wanna add some custom validators, style or add some dependent validators or other things will became a chimera this component, definetly will kill productivity on quick prototyping. If you wanna handle a big bulks of forms, i suggest you to look at using a dynamic form.

Sᴀᴍ Onᴇᴌᴀ
29.5k16 gold badges45 silver badges201 bronze badges
answered Feb 7, 2019 at 12:08
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.