如何在Angular 2中动态添加和删除表单字段 [英] How to dynamically add and remove form fields in Angular 2

查看:78
本文介绍了如何在Angular 2中动态添加和删除表单字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在用户单击添加按钮时动态添加输入字段,并且对于每个表单字段必须有一个删除按钮,当用户单击必须删除表单字段时,我需要使用Angular来实现2,因为我是Angular 2的新手,请帮助我完成它

I'm trying to add input fields dynamically while the user clicks the add button and for each form field there must be a remove button, when the user clicks that the form fields must be removed, I need to achieve this using Angular 2, as I'm new to Angular 2 please help me to complete it

我尝试过的

我创建了一组字段(3个选择框和1个文本框),创建了一个名为添加字段的按钮,但是我尝试了在angular 1.x中正常工作,但是在angular 2中我不知道如何要完成此操作,这是我全部工作的链接

I have created a set of fields (3 select box and 1 text box), created a button called add fields, but I have tried it in angular 1.x its working fine but in angular 2 I don't know how to complete it, this is link of my full work

app/app.component.ts
 import {
    Component
  }
from '@angular/core';
  @Component({
    selector: 'my-app',
    template: `
    <h1>{{title}}</h1>
    <div class="container">
    <button class="btn btn-success bt-sm">add</button>
    <form role="form" calss="form-inline">
    <div class="form-group col-xs-3">
    <label>Select State:</label>
    <select class="form-control" [(ngModel)]="rules.State" id="sel1">
            <option>State1</option>
            <option>State2</option>
            <option>State3</option>
            <option>State4</option>
</select>
     </div>
    <div class="form-group col-xs-3">
<label>Rule:</label>
     <input type="text" data-toggle="modal" data-target="#myModal" class="form-                   control">
    </div>
<div class="form-group col-xs-3">
<label>Pass State :</label>
    <select class="form-control" [(ngModel)]="rules.pass">
    <option>State1</option>
    <option>State2</option>
    <option>State3</option>
    <option>State4</option>
</select>
 </div>
 <div class="form-group col-xs-3">
    <label>Fail State:</label>
        <select class="form-control" [(ngModel)]="rules.fail">
        <option>State1</option>
        <option>State2</option>
        <option>State3</option>
     <option>State4</option>
     </select>
         </div>
    </form>
     </div>
 <div class="modal fade" id="myModal" role="dialog">
      <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                     <button type="button" class="close" data-dismiss="modal">&times    </button>
                    <h4 class="modal-title">Rules Configuration</h4>
                </div>
                <div class="modal-body">
                 <p>Rules</p>
                </div>
                 <div class="modal-footer">
                 <button type="button" class="btn btn-default" data-  dismiss="modal">Close</button>
                </div>
             </div>

                </div>
                 </div>
`
    })
    export class AppComponent {
            title = 'Rule Engine Demo';
          rules: Rules = {
                  State: '',
                  pass: '',
                 fail: ''
                };

推荐答案

这已经晚了几个月,但我认为我会根据

This is a few months late but I thought I'd provide my solution based on this here tutorial. The gist of it is that it's a lot easier to manage once you change the way you approach forms.

首先,使用ReactiveFormsModule代替普通的FormsModule或除常规的FormsModule之外使用.使用反应式表单,您可以在组件/服务中创建表单,然后将其插入页面,而不是页面本身生成表单.它的代码更多,但可测试性更高,更灵活,而且据我所知,它是制作大量非平凡表单的最佳方法.

First, use ReactiveFormsModule instead of or in addition to the normal FormsModule. With reactive forms you create your forms in your components/services and then plug them into your page instead of your page generating the form itself. It's a bit more code but it's a lot more testable, a lot more flexible, and as far as I can tell the best way to make a lot of non-trivial forms.

从概念上讲,最终结果将看起来像这样:

The end result will look a little like this, conceptually:

  • 您有一个基础FormGroup,其中包含整个表单所需的任何FormControl实例.例如,在我链接的教程中,假设您需要一个表单,用户可以在其中输入一次姓名,然后输入任意数量的地址.所有一次性字段输入都将在此基本表单组中.

  • You have one base FormGroup with whatever FormControl instances you need for the entirety of the form. For example, as in the tutorial I linked to, lets say you want a form where a user can input their name once and then any number of addresses. All of the one-time field inputs would be in this base form group.

在该FormGroup实例内部,将有一个或多个FormArray实例. FormArray基本上是将多个控件组合在一起并对其进行迭代的一种方法.您还可以在数组中放置多个FormGroup实例,并将它们用作嵌套在较大表单中的本质上的迷你表单".

Inside that FormGroup instance there will be one or more FormArray instances. A FormArray is basically a way to group multiple controls together and iterate over them. You can also put multiple FormGroup instances in your array and use those as essentially "mini-forms" nested within your larger form.

通过在动态FormArray中嵌套多个FormGroup和/或FormControl实例,您可以控制有效性并将表单作为一个由多个动态部分组成的大型反应块进行管理.例如,如果您要在允许用户提交之前检查每个输入是否有效,则一个子表单的有效性将冒泡"到顶级表单,并且整个表单都将变为无效,因此很容易管理动态输入.

By nesting multiple FormGroup and/or FormControl instances within a dynamic FormArray, you can control validity and manage the form as one, big, reactive piece made up of several dynamic parts. For example, if you want to check if every single input is valid before allowing the user to submit, the validity of one sub-form will "bubble up" to the top-level form and the entire form becomes invalid, making it easy to manage dynamic inputs.

由于FormArray本质上是围绕数组接口的包装器,但是对于表单,您可以随时推,弹出,插入和删除控件,而无需重新创建表单或进行复杂的交互./p>

As a FormArray is, essentially, a wrapper around an array interface but for form pieces, you can push, pop, insert, and remove controls at any time without recreating the form or doing complex interactions.

万一我链接的教程崩溃了,您可以在此处自己实现一些示例代码(我的示例使用TypeScript),以说明基本思想:

In case the tutorial I linked to goes down, here some sample code you can implement yourself (my examples use TypeScript) that illustrate the basic ideas:

基本组件代码:

import { Component, Input, OnInit } from '@angular/core';
import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'my-form-component',
  templateUrl: './my-form.component.html'
})
export class MyFormComponent implements OnInit {
    @Input() inputArray: ArrayType[];
    myForm: FormGroup;

    constructor(private fb: FormBuilder) {}
    ngOnInit(): void {
        let newForm = this.fb.group({
            appearsOnce: ['InitialValue', [Validators.required, Validators.maxLength(25)]],
            formArray: this.fb.array([])
        });

        const arrayControl = <FormArray>newForm.controls['formArray'];
        this.inputArray.forEach(item => {
            let newGroup = this.fb.group({
                itemPropertyOne: ['InitialValue', [Validators.required]],
                itemPropertyTwo: ['InitialValue', [Validators.minLength(5), Validators.maxLength(20)]]
            });
            arrayControl.push(newGroup);
        });

        this.myForm = newForm;
    }
    addInput(): void {
        const arrayControl = <FormArray>this.myForm.controls['formArray'];
        let newGroup = this.fb.group({

            /* Fill this in identically to the one in ngOnInit */

        });
        arrayControl.push(newGroup);
    }
    delInput(index: number): void {
        const arrayControl = <FormArray>this.myForm.controls['formArray'];
        arrayControl.removeAt(index);
    }
    onSubmit(): void {
        console.log(this.myForm.value);
        // Your form value is outputted as a JavaScript object.
        // Parse it as JSON or take the values necessary to use as you like
    }
}

子组件代码 :(每个新输入字段一个,以保持环境整洁)

Sub-Component Code: (one for each new input field, to keep things clean)

import { Component, Input } from '@angular/core';
import { FormGroup } from '@angular/forms';

@Component({
    selector: 'my-form-sub-component',
    templateUrl: './my-form-sub-component.html'
})
export class MyFormSubComponent {
    @Input() myForm: FormGroup; // This component is passed a FormGroup from the base component template
}

基本组件HTML

<form [formGroup]="myForm" (ngSubmit)="onSubmit()" novalidate>
    <label>Appears Once:</label>
    <input type="text" formControlName="appearsOnce" />

    <div formArrayName="formArray">
        <div *ngFor="let control of myForm.controls['formArray'].controls; let i = index">
            <button type="button" (click)="delInput(i)">Delete</button>
            <my-form-sub-component [myForm]="myForm.controls.formArray.controls[i]"></my-form-sub-component>
        </div>
    </div>
    <button type="button" (click)="addInput()">Add</button>
    <button type="submit" [disabled]="!myForm.valid">Save</button>
</form>

子组件HTML

<div [formGroup]="form">
    <label>Property One: </label>
    <input type="text" formControlName="propertyOne"/>

    <label >Property Two: </label>
    <input type="number" formControlName="propertyTwo"/>
</div>

在上面的代码中,我基本上有一个代表表单基础的组件,然后每个子组件在位于基础FormGroup内的FormArray中管理自己的FormGroup实例.基本模板将子组传递到子组件,然后您可以动态处理整个表单的验证.

In the above code I basically have a component that represents the base of the form and then each sub-component manages its own FormGroup instance within the FormArray situated inside the base FormGroup. The base template passes along the sub-group to the sub-component and then you can handle validation for the entire form dynamically.

此外,通过策略性地从表单中插入和删除组件,重新安排组件的顺序变得很简单.它可以(似乎)与任意数量的输入一起使用,因为它们与名称不冲突(据我所知,这是模板驱动的表单的一大缺点),并且您仍然保留了许多自动验证功能.这种方法的唯一缺点"是,除了编写更多代码之外,您还必须重新学习表单的工作方式.但是,随着操作的进行,这将为更大,更动态的表单打开可能性.

Also, this makes it trivial to re-order component by strategically inserting and removing them from the form. It works with (seemingly) any number of inputs as they don't conflict with names (a big downside of template-driven forms as far as I'm aware) and you still retain pretty much automatic validation. The only "downside" of this approach is, besides writing a little more code, you do have to relearn how forms work. However, this will open up possibilities for much larger and more dynamic forms as you go on.

如果您有任何疑问或想指出一些错误,请继续.我只是根据上周我自己做的事情(其中包括更改名称和其他内容)输入了上面的代码.属性被忽略了,但是应该很简单.上面的代码和我自己的代码之间的唯一主要区别是,我将所有的表单构建都移到了一个从组件调用的单独服务中,这样就少了一些混乱.

If you have any questions or want to point out some errors, go ahead. I just typed up the above code based on something I did myself this past week with the names changed and other misc. properties left out, but it should be straightforward. The only major difference between the above code and my own is that I moved all of the form-building to a separate service that's called from the component so it's a bit less messy.

这篇关于如何在Angular 2中动态添加和删除表单字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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