Angular 2 动态嵌套表单 [英] Angular 2 Dynamic Nested Form

查看:48
本文介绍了Angular 2 动态嵌套表单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上我想创建一个带有嵌套对象的动态表单,如下图:

  • 收益在模型的数组中
  • 我们应该能够根据需要添加/删除回报.
  • 表单应同步底层表单控件和模型
  • 支付的数量是任意的,应该从模型加载到表单中

我找不到如何在 Angular 2 中执行此操作的工作示例,尽管这在 Angular 1 中很容易做到.

<小时>

下面是我最初的问题,我已经更新了它以进行澄清(见上文):

首先我只想指出,我知道几天前刚刚发布了新版本的 Angular 2 rc.2.因此,用于创建动态嵌套表单的代码可能已经更改了一些,但没有足够的文档来解决这个问题.

在 Angular 2 的最新版本中(我目前使用的是 rc.1,但计划更新到 rc.2)我需要创建一个这样的表单(视图的伪代码):

<input type="text" ngControl="name"><div *ngFor="让费用支付费用;让 i = 指数;"控制组=费用"><input type="text" ngControl="expense.amount" [(ngModel)]="myModel.expenses[i].amount"><input type="checkbox" ngControl="expense.final" [(ngModel)]="myModel.expenses[i].final">

<a class="button" (click)="addExpenseControl()">添加</a><a class="button" (click)="deleteExpenseControl()">Delete</a></表单>

所以上面的伪代码不起作用,但老实说,由于缺乏文档,我无法弄清楚如何连接这样的东西.有一些关于嵌套 ControlGroup 的教程,但这不适合这里的情况,因为我们需要能够动态添加和删除控制组,而且我还需要能够将它们与模型同步.

我发现这个 plunkr 这里由 Angular 团队提供,它允许将控件添加到表单中——但这不是添加/删除 ControlGroup,而是使用 ControlArray,我不确定这是否适用于此处?

我非常熟悉使用较新的基于模型的 Angular 2 表单,但是我正在抓紧资源以正确嵌套它们(动态!),并将此嵌套数据绑定到主表单模型中.我将如何引用视图中的嵌套控件?上面的伪代码甚至接近吗?我会从我的控制器发布代码,但老实说,当涉及到上面的嵌套费用 (ControlGroup ??) 时,我不知道从哪里开始......

解决方案

我不得不自己解决这个问题,因为 Angular 2 中的表单似乎仍在变化,而且我还没有看到任何其他类似的例子(尽管这似乎是一个非常常见的用例).

这是使用 Angular2 RC3 的工作示例的 plunkr.

我正在使用 本文档中更新的 Angular 2 表单代码.

app.component.ts(包含表单):

import { Component } from '@angular/core';从@angular/forms"导入{REACTIVE_FORM_DIRECTIVES、FormControl、FormGroup、FormArray};@成分({选择器:'我的应用',templateUrl: 'app/app.html',指令:[REACTIVE_FORM_DIRECTIVES],提供者:[]})导出类 AppComponent {表格:表格组;我的模型:任何;构造函数(){//初始化表单的模型以保持同步.//通常你会从后端 API 获取它this.myModel = {姓名:乔安娜·杰德泽西克",回报:[{金额:111.11,日期:2016 年 1 月 1 日",最终:假},{金额:222.22,日期:2016 年 1 月 2 日",最终:真实}]}//用空的 FormArray 初始化表单以获取收益this.form = new FormGroup({名称:new FormControl(''),回报:新的 FormArray([])});//现在我们手动使用模型并为每个 PayOff 将 FormGroup 推送到表单的 FormArraythis.myModel.payOffs.forEach((po) =>this.form.controls.payOffs.push(this.createPayOffFormGroup(po)));}createPayOffFormGroup(payOffObj) {console.log("payOffObj", payOffObj);返回新的表单组({金额:新的 FormControl(payOffObj.amount),日期:新的FormControl(payOffObj.date),最终:新的FormControl(payOffObj.final)});}addPayOff(事件){event.preventDefault();//确保此按钮不会尝试提交表单var emptyPayOff = {amount: null, date: null, final: false};//为模型和表单控件添加回报,因为我认为 Angular 还没有任何方法可以自动执行此操作this.myModel.payOffs.push(emptyPayOff);this.form.controls.payOffs.push(this.createPayOffFormGroup(emptyPayOff));console.log("添加新的支付", this.form.controls.payOffs)}deletePayOff(索引:编号){//从模型和 FormArray 中删除收益this.myModel.payOffs.splice(index, 1);this.form.controls.payOffs.removeAt(index);}}

注意上面,我手动将新的 FormGroup 对象推送到 form.controls.payOffs 数组中,该数组是一个 FormArray 对象.

app.html(包含表单 html):

 <label>名称</label><input type="text" formControlName="name" [(ngModel)]="myModel.name" placeholder="Name"><p>回报</p><表类=简单表"><tr><th>数量</th><第>日期</th><th>决赛?</th><th></th></tr><tr *ngFor="let po of form.find('payOffs').controls; let i = index"><td><input type="text" size=10 [formControl]="po.controls.amount" [(ngModel)]="myModel.payOffs[i].amount"></td><td><input type="text" [formControl]="po.controls.date" [(ngModel)]="myModel.payOffs[i].date"></td><td><input type="checkbox" [formControl]="po.controls.final" [(ngModel)]="myModel.payOffs[i].final"></td><td><button (click)="deletePayOff(i)" style="color: white; background: rgba(255, 0, 0, .5)">x</button></td></tr></tbody><tr><td colspan="4" style="text-align: center; padding: .5em;"><button (click)="addPayOff($event)" style="color: white; background: rgba(0, 150, 0, 1)">添加支付</button></td></tr></表单>

在 html 表单中,我使用如下语句将表单链接到输入模型:

... [formControl]="po.controls.amount" [(ngModel)]="myModel.payOffs[i].amount" ...

Basically I want to create a dynamic form with nested objects like the picture below:

  • Pay offs are in an array on the model
  • We should be able to add/remove pay offs as needed.
  • The form should sync underlying form controls and model
  • The number of pay offs is arbitrary and should be loaded into the form from the model

There are no working examples that I could find as how to do this in Angular 2, although this was really easy to do in Angular 1.


Below is my original question, I've since updated it for clarification (see above):

First I just wanted to point out that I'm aware that a new version of Angular 2 rc.2 has just been released a few days ago. So the code for creating a dynamic, nested form may have changed some but there's not enough documentation to figure this out.

In the latest version(s) of Angular 2 (I'm currently using rc.1 but planning to update to rc.2) I need to create a form like this (pseudo-code of view):

<form [ngFormModel]="form" (ngSubmit)="onSubmit()">
  <input type="text" ngControl="name">

  <div *ngFor="let expense for expenses; let i = index;" control-group="expenses">
    <input type="text" ngControl="expense.amount" [(ngModel)]="myModel.expenses[i].amount"> 
    <input type="checkbox" ngControl="expense.final" [(ngModel)]="myModel.expenses[i].final"> 
  </div>

  <a class="button" (click)="addExpenseControl()">Add</a>
  <a class="button" (click)="deleteExpenseControl()">Delete</a>
</form>

So the pseudo-code above won't work but to be honest because of lack of documentation I can't figure out how to wire something like this up. There's a few tutorials about nested ControlGroup but this won't fit the case here since we need to be able to dynamically add and remove control groups, and also I need to be able to sync them with a model.

I found this plunkr here provided by Angular team which allows adding of Controls to a form--but this is not adding/removing a ControlGroup, rather it's using ControlArray and I'm not sure if that applies here?

I'm very familiar with using the newer model-based Angular 2 forms however I'm grasping for resources in order to properly nest them (dynamically!), and tie this nested data into the main form model. How would I refer to nested controls in the view? Is the pseudo-code above even close? I'd post code from my controller but honestly I wouldn't know where to start when it comes to the nested expenses (ControlGroup ??) above...

解决方案

I had to figure this out on my own because it seems that forms are still changing in Angular 2 and I've not seen any other examples similar to this (although it seems like a very common use-case).

Here is a plunkr of working example using Angular2 RC3.

I am using updated Angular 2 form code from this document.

app.component.ts (contains the form):

import { Component } from '@angular/core';
import {REACTIVE_FORM_DIRECTIVES, FormControl, FormGroup, FormArray} from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: 'app/app.html',
  directives: [REACTIVE_FORM_DIRECTIVES],
  providers:  []
})
export class AppComponent {
  form: FormGroup;
  myModel:any;

  constructor() {
    // initializing a model for the form to keep in sync with. 
    // usually you'd grab this from a backend API
    this.myModel = {
      name: "Joanna Jedrzejczyk",
      payOffs: [
        {amount: 111.11, date: "Jan 1, 2016", final: false},
        {amount: 222.22, date: "Jan 2, 2016", final: true}
        ]
    }

    // initialize form with empty FormArray for payOffs
    this.form = new FormGroup({
      name: new FormControl(''),
      payOffs: new FormArray([])
    });

    // now we manually use the model and push a FormGroup into the form's FormArray for each PayOff
    this.myModel.payOffs.forEach( 
      (po) => 
        this.form.controls.payOffs.push(this.createPayOffFormGroup(po))
    );
  }

  createPayOffFormGroup(payOffObj) {
    console.log("payOffObj", payOffObj);
    return new FormGroup({
      amount: new FormControl(payOffObj.amount),
      date: new FormControl(payOffObj.date),
      final: new FormControl(payOffObj.final)
    });
  }

  addPayOff(event) {
    event.preventDefault(); // ensure this button doesn't try to submit the form
    var emptyPayOff = {amount: null, date: null, final: false};

    // add pay off to both the model and to form controls because I don't think Angular has any way to do this automagically yet
    this.myModel.payOffs.push(emptyPayOff);
    this.form.controls.payOffs.push(this.createPayOffFormGroup(emptyPayOff));
    console.log("Added New Pay Off", this.form.controls.payOffs)
  }

  deletePayOff(index:number) {
    // delete payoff from both the model and the FormArray
    this.myModel.payOffs.splice(index, 1);
    this.form.controls.payOffs.removeAt(index);
  }
}

Notice above that I manually push new FormGroup objects into the form.controls.payOffs array, which is a FormArray object.

app.html (contains form html):

  <form (ngSubmit)="onSubmit()" [formGroup]="form">

    <label>Name</label>
    <input type="text" formControlName="name" [(ngModel)]="myModel.name" placeholder="Name">

    <p>Pay Offs</p>
    <table class="simple-table">
      <tr>
        <th>Amount</th>
        <th>Date</th>
        <th>Final?</th>
        <th></th>
      </tr>
    <tbody>
      <tr *ngFor="let po of form.find('payOffs').controls; let i = index">
        <td>
          <input type="text" size=10 [formControl]="po.controls.amount" [(ngModel)]="myModel.payOffs[i].amount">
        </td>
        <td>
          <input type="text" [formControl]="po.controls.date" [(ngModel)]="myModel.payOffs[i].date">
        </td>
        <td>
          <input type="checkbox" [formControl]="po.controls.final" [(ngModel)]="myModel.payOffs[i].final">
        </td>
        <td>
          <button (click)="deletePayOff(i)" style="color: white; background: rgba(255, 0, 0, .5)">x</button>
        </td>
      </tr>
    </tbody>
    <tr>
      <td colspan="4" style="text-align: center; padding: .5em;">
        <button (click)="addPayOff($event)" style="color: white; background: rgba(0, 150, 0, 1)">Add Pay Off</button>
      </td>
    </tr>
    </table>

  </form>

In the html form I link the form to the model on the inputs with statements like so:

... [formControl]="po.controls.amount" [(ngModel)]="myModel.payOffs[i].amount" ...

这篇关于Angular 2 动态嵌套表单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆