2017-09-25 148 views
0

我正在开发一个Angular 4.X项目,并且我正在按钮单击时创建一些HTML输入字段(主要是文本类型)。动态创建输入框工作正常,但我无法对这些字段进行验证。我收到以下错误。Angular 2表单验证动态字段

无法读取属性为空(...)

我已经创建了一个相同的普拉克的“无效”。以下是我创建的链接普拉克 -

https://plnkr.co/edit/PCFD43GK91zo2ivQ9lf7?p=preview 为了便于参考,请找到下面的代码 -

//Root app component 
import {Component, NgModule} from '@angular/core' 
import {BrowserModule} from '@angular/platform-browser' 
import { FormBuilder, FormGroup, Validators, FormArray, FormControl } from '@angular/forms'; 
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; 

@Component({ 
    selector: 'my-app', 
    template: `<hr> 
       <div> 
       <form [formGroup]="orderForm" (ngSubmit)="OnSubmit(orderForm.value)"> 
        <div> 
        <input type="text" formControlName="customerName"/> 
        <input type="text" formControlName="email"/> 
        </div> 
        <div formArrayName="items" *ngFor="let item of items.controls; let i = index;"> 
        <div [formGroupName]="i"> 
         <input type="text" formControlName="name" placeholder="Item name"/> 
         <small *ngIf="IsValidField('name')" class="text-danger"> 
         Name is required 
         </small> 
         <input type="text" formControlName="description" placeholder="Item description"/> 
         <small *ngIf="IsValidField('description')" class="text-danger"> 
         Description is required 
         </small> 
         <input type="text" formControlName="price" placeholder="Item price"/> 
         <small *ngIf="IsValidField('price')" class="text-danger"> 
         Price is required 
         </small> 
        </div> 
        Chosen name: {{ orderForm.controls.items.controls[i].controls.name.value }} 
        </div> 
        <button type="submit">Save</button> 
        <button type="button" (click)="addItem()">Add More</button> 
       </form> 
       <div>`, 
}) 

export class App { 

    constructor(private formBuilder: FormBuilder) { } 

    public orderForm: FormGroup; 



    ngOnInit() { 
     this.orderForm = this.formBuilder.group({ 
     customerName: '', 
     email: '', 
     items: this.formBuilder.array([ this.createItem()]) 
     }); 
    } 

createItem(): FormGroup { 
    return this.formBuilder.group({ 
     name: ['',[Validators.required,Validators.maxLength(10)]], 
     description: '', 
     price: ['',[Validators.required,Validators.pattern("[(0-9)*]")]] 
    }); 
    } 

    get items(): FormArray { 
    return this.orderForm.get('items') as FormArray; 
    }; 

    addItem(): void { 
    this.items.push(this.createItem()); 
    } 

    public OnSubmit(formValue: any) { 
     console.log(JSON.stringify(formValue)); 
    } 

    public IsValidField(field: string) { 
     return (this.orderForm.get(field).invalid && this.orderForm.get(field).touched) || (this.orderForm.get(field).invalid && this.orderForm); 
    } 

} 

@NgModule({ 
    imports: [ BrowserModule, FormsModule, ReactiveFormsModule ], 
    declarations: [ App ], 
    bootstrap: [ App ] 
}) 
export class AppModule {} 

任何帮助,将不胜感激。

回答

0

您正在寻找orderForm内有动态添加的表单域,但并不适用于此。在访问其值之前,您应该正确查询表单。我画下图将帮助你理解动态创建的表单体系结构。

orderForm (FormGroup) 
    | 
    - Items (FormArray) 
    | 
    - 0 (FormGroup) 
     - name 
     - description 
     - price 
    | 
    - 1 (FormGroup) 
     - name 
     - description 
     - price 
    | 
    |......... 

所以IsValidField功能应该得到formArray元素,字段名的index。通过它可以轻松查询表单元素。

public IsValidField(i: number, field: any) { 
    var f = this.orderForm 
      .get('items') //retrieve items FormArray 
      .get(i.toString()) //retrieve items FormGroup 
      .get(field); //retrieve items form field 
    return (f.invalid && f.touched) || (f.invalid && this.orderForm); 
} 

然后在*ngIf发生相应的变化IsValidField函数调用。

*ngIf="IsValidField(i, 'name')" 
*ngIf="IsValidField(i, 'description')" 
*ngIf="IsValidField(i, 'price')" 

Demo Plunker

+0

感谢潘卡它确实帮助。你能告诉我如何使用数据填充这些字段,我试图做到这一点,但它不工作。这是[链接]的Plunker(https://plnkr.co/edit/PCFD43GK91zo2ivQ9lf7?p=preview) –

+0

@AmitAnand使用'.patchValue'填充值 –

+0

但是,我将如何做到这一点的多个领域和太动态。你可以看看Plunker并为我提供解决方案。 –