【问题标题】:Dynamically adding form elements using formGroup in Angular reactive forms在 Angular 反应式表单中使用 formGroup 动态添加表单元素
【发布时间】:2018-06-27 02:19:17
【问题描述】:

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

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

【问题讨论】:

  • 您必须从发行者组件发送 issuerConfigForm 作为输入,否则您必须通知动态表单以按事件重新生成 formGroup。 t问题是一旦您单击 addBtn 方法,您的代码 ngOnint 就不会调用
  • @Indrakumara,你能告诉我在哪里可以更改代码。

标签: angular angular-reactive-forms


【解决方案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>


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

【讨论】:

  • @Duong,感谢您的宝贵回答。我正在使用 'fb.array' 使用您的代码添加新控制器,并且工作正常。假设如果我想再添加一个不同的字段,是否需要将元素推入数组或清除数组并再次推入?
  • @vishnu 如果您使用fb.array 在表单中使用我的代码,例如new controller,当您更新fields 时,我认为您需要再次重新渲染form
【解决方案2】:

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

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多