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

我试过的

我创建了一组字段(3个 Select 框和1个文本框),创建了一个名为"添加字段"的按钮,但我在angular 1中try 过.它的工作很好,但在angular 2中,我不知道如何完成它,这是我全部工作的link

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 here tutorial的解决方案.要点是,一旦你改变了处理表单的方式,管理起来就容易多了.

首先,使用ReactiveFormsModule来代替或补充正常的FormsModule.使用react 式表单,您可以在组件/服务中创建表单,然后将它们插入页面,而不是页面本身生成表单.它的代码要多一点,但它的可测试性要高得多,灵活性也要高得多,而且就我所知,制作许多非平凡表单的最佳方法.

从概念上讲,最终结果会有点像这样:

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

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

  • 通过在动态FormArray中嵌套多个FormGroup和/或FormControl实例,您可以控制有效性并将表单作为由多个动态部分组成的一个大的react 性部分进行管理.例如,如果您希望在允许用户提交之前判断每一次输入是否有效,则一个子窗体的有效性将"泡沫"上升到顶级窗体,整个窗体将变为无效,从而便于管理动态输入.

  • 实际上,FormArray是数组接口的包装器,但对于表单块,您可以随时推送、弹出、插入和删除控件,而无需重新创建表单或进行复杂的交互.

如果我链接到的教程失败了,下面是一些示例代码,您可以自己实现(我的示例使用TypeScript),它们说明了基本思想:

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:(每个新输入字段一个,以保持整洁)

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>

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

此外,这使得通过有策略地在表单中插入和删除组件来重新排序组件变得非常简单.它可以(似乎)使用任何数量的输入,因为它们与名称不冲突(据我所知,这是模板驱动表单的一大缺点),而且您仍然保留了相当多的自动验证.这种方法唯一的"缺点"是,除了编写更多的代码之外,您还必须重新学习表单是如何工作的.但是,随着您的继续,这将为更大、更动态的表单打开可能性.

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

Angular相关问答推荐

Rxjs重置执行后的可观察延迟并重新调度Angular

确保我的角库S服务构建提供独立的友好提供功能

使用jsPDF生成带有图像的PDF时出现灰色条纹

ANGLING HTTP.GET()返回包含数据的数组

Angular react 形式验证问题

将ngModel绑定到@Input属性是不是一种糟糕的做法?

在以下位置升级到Angular 16 Break Sharepoint广告:This._history.replaceState不是函数

NX如何在前端和后端使用一个接口库

导入 AngularFirestoreModule 时出现问题:此类型参数可能需要 `extends firebase.firestore.DocumentData` 约束.

Angular 测试被认为是成功的,即使有错误

如何将新的 FormGroup 或 FormControl 添加到表单

错误:formControlName 必须与父 formGroup 指令一起使用.您需要添加一个 formGroup 指令

错误 TS1086:无法在 Angular 9 的环境上下文中声明访问器

EmptyError: no elements in sequence

Angular 2:无法绑定到 x,因为它不是已知的本机属性

如何添加/设置环境 Angular 6 angular.json 文件

请求 http.GET 时发送的 Angular2 OPTIONS 方法

如何在 Angular2 中的所有请求的请求标头中发送Cookie?

Angular 5 测试:如何获取对子组件的引用

Angular 4中的md-select中的onselected事件