我试过了
我创建了一组字段(3个选择框和1个文本框),创建了一个称为添加字段的按钮,但是我已经尝试过它的角度为1.x的工作正常但是在角度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">× </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: '' };
解决方法
首先,使用ReactiveFormsModule,而不是正常的FormsModule或除此之外.使用反应式表单,您可以在组件/服务中创建表单,然后将其插入到页面中,而不是生成表单本身的页面.这是一个更多的代码,但它是更多的可测试,更多的灵活性,就我可以告诉最好的方式来制作很多非平凡的形式.
最终结果将在这个概念上看起来有点像:
>您有一个基础FormGroup与您需要整个表单的FormControl实例.例如,在我链接的教程中,让我们说你想要一个表单,用户可以在其中输入一个名字,然后输入任意数量的地址.所有的一次性现场输入将在该基本形式组中.
>在FormGroup实例里面会有一个或多个FormArray实例. FormArray基本上是将多个控件组合在一起并对其进行迭代的一种方式.您还可以将多个FormGroup实例放在数组中,并将其作为基本上“嵌入式”的嵌套在更大的形式中.
>通过在动态FormArray中嵌套多个FormGroup和/或FormControl实例,您可以控制有效性并将表单管理为由多个动态部分组成的一个大型反应片.例如,如果要在允许用户提交之前检查每个单个输入是否有效,则一个子表单的有效性将“冒泡”到顶级表单,并且整个表单变得无效,从而易于管理动态输入.
>由于FormArray本质上是一个围绕数组接口的包装器,但是对于表单,您可以随时推送,弹出,插入和删除控件,而无需重新创建表单或进行复杂的交互.
如果我链接的教程下降,这里有一些示例代码可以实现自己(我的示例使用TypeScript)来说明基本的想法:
基本组件代码:
import { Component,Input,OnInit } from '@angular/core'; import { FormArray,FormBuilder,FormGroup } 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 } }
子组件代码:(每个新的输入字段一个,保持清洁)
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实例.基本模板沿着子组传递到子组件,然后可以动态地处理整个表单的验证.
此外,这样做通过从表单中策略性地插入和删除组件来重新排序组件是微不足道的.它与(似乎)任何数量的输入一起工作,因为它们不会与名称冲突(据我所知,模板驱动形式的一大缺点),并且您仍然保留了很多自动验证.这种方法的唯一“缺点”就是除了编写更多的代码之外,你必须重新学习表单的工作原理.但是,随着时间的推移,这将为更多更有活力的形式开辟可能性.
如果您有任何问题或想指出一些错误,请继续.我刚刚打了上面的代码,基于我过去一周的这个名字改变了一些其他的杂项.属性被遗弃,但应该是直截了当的.上面的代码和我自己之间的唯一主要区别是,我将所有的form-building都转移到了从组件中调用的单独的服务中,这样就不那么麻烦了.