在Angular反应表单中使用formGroup动态添加表单元素

时间:2018-06-26 03:39:36

标签: angular angular-reactive-forms

我有表单字段,当用户单击添加按钮时,需要添加一些其他字段。如果用户单击“添加”按钮,则新表单将以模式形式打开他可以在其中配置字段名称,类型和值的窗口)。如何将新创建的动态元素添加到现有表单。

我尝试使用以下代码,但未添加新生成的字段。
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);
    }
}

2 个答案:

答案 0 :(得分:1)

您可以按照以下示例呈现动态表单:

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>

enter image description here


最后,您应该使用@Outputform.value发送到<issuer component>。我认为我们应该更清楚地定义the controls structure data,以便于理解和呈现。

答案 1 :(得分:0)

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() {
  }

}