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

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

问题描述

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

我的尝试

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

app/app.component.ts进口 {成分}来自'@angular/core';@成分({选择器:'我的应用',模板:`<h1>{{title}}</h1><div class="容器"><button class="btn btn-success bt-sm">add</button><form role="form" calss="form-inline"><div class="form-group col-xs-3"><label>选择状态:</label><select class="form-control" [(ngModel)]="rules.State" id="sel1"><option>State1</option><option>State2</option><option>State3</option><option>State4</option></选择>

<div class="form-group col-xs-3"><label>规则:</label><input type="text" data-toggle="modal" data-target="#myModal" class="form-control">

<div class="form-group col-xs-3"><label>通过状态:</label><select class="form-control" [(ngModel)]="rules.pass"><option>State1</option><option>State2</option><option>State3</option><option>State4</option></选择>

<div class="form-group col-xs-3"><label>失败状态:</label><select class="form-control" [(ngModel)]="rules.fail"><option>State1</option><option>State2</option><option>State3</option><option>State4</option></选择>

</表单>

<div class="modalfade" 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">规则配置</h4>

<div class="modal-body"><p>规则</p>

<div class="modal-footer"><button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>

`})导出类 AppComponent {title = '规则引擎演示';规则:规则 = {状态: '',经过: '',失败: ''};

解决方案

这已经晚了几个月,但我想我会根据 本教程.其要点是,一旦您改变处理表单的方式,管理起来就会容易得多.

首先,使用ReactiveFormsModule 代替普通的FormsModule 或与其一起使用.使用响应式表单,您可以在组件/服务中创建表单,然后将它们插入页面而不是页面生成表单本身.这是更多的代码,但它更易于测试,更灵活,据我所知,这是制作大量非平凡形式的最佳方法.

最终结果看起来有点像这样,概念上:

如果我链接的教程失败了,这里有一些示例代码,您可以自己实现(我的示例使用 TypeScript)来说明基本思想:

基本组件代码:

import { Component, Input, OnInit } from '@angular/core';从@angular/forms"导入 { FormArray, FormBuilder, FormGroup, Validators };@成分({选择器:'我的表单组件',templateUrl: './my-form.component.html'})导出类 MyFormComponent 实现 OnInit {@Input() inputArray: ArrayType[];我的表格:表格组;构造函数(私有 fb:FormBuilder){}ngOnInit(): 无效 {让 newForm = this.fb.group({出现一次:['InitialValue', [Validators.required, Validators.maxLength(25)]],formArray: this.fb.array([])});const arrayControl = <FormArray>newForm.controls['formArray'];this.inputArray.forEach(item => {让 newGroup = this.fb.group({itemPropertyOne: ['InitialValue', [Validators.required]],itemPropertyTwo: ['InitialValue', [Validators.minLength(5), Validators.maxLength(20)]]});arrayControl.push(newGroup);});this.myForm = newForm;}添加输入():无效{const arrayControl = <FormArray>this.myForm.controls['formArray'];让 newGroup = this.fb.group({/* 填写与 ngOnInit 中相同的内容 */});arrayControl.push(newGroup);}delInput(索引:数字):无效{const arrayControl = <FormArray>this.myForm.controls['formArray'];arrayControl.removeAt(index);}onSubmit(): void {console.log(this.myForm.value);//您的表单值作为 JavaScript 对象输出.//将其解析为 JSON 或根据需要采用必要的值}}

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

import { Component, Input } from '@angular/core';从@angular/forms"导入{FormGroup};@成分({选择器:我的表单子组件",templateUrl: './my-form-sub-component.html'})导出类 MyFormSubComponent {@Input() myForm: FormGroup;//该组件从基础组件模板中传递了一个 FormGroup}

基本组件 HTML

<label>出现一次:</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)">删除</button><my-form-sub-component [myForm]="myForm.controls.formArray.controls[i]"></my-form-sub-component>

<button type="button" (click)="addInput()">添加</button><button type="submit" [disabled]="!myForm.valid">保存</button></表单>

子组件 HTML

<label>属性一:</label><input type="text" formControlName="propertyOne"/><label >属性二:</label><input type="number" formControlName="propertyTwo"/>

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

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

如果您有任何问题或想指出一些错误,请继续.我只是根据我上周自己做的事情输入了上面的代码,名称已更改和其他杂项.属性被遗漏了,但它应该是直截了当的.上面的代码和我自己的代码之间的唯一主要区别是,我将所有的表单构建移到了从组件调用的单独服务中,因此它不那么混乱.

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

What I have tried

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.

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:

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:

Base Component code:

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
}

Base Component 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>

Sub-Component HTML

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

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

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天全站免登陆