如何在 angular 2 中以动态形式响应验证消息

how to reactive validation messages in dynamic forms in angular 2

我正在学习 angular 2.

中的反应式动态形式

我想像 angular.io 食谱表单验证那样验证消息。

像这样:

 this.heroForm.valueChanges
  .subscribe(data => this.onValueChanged(data));

所以我订阅动态表单中的表单值更改

但是奇怪的事情发生了,比如:

我群里有两个地址,一个有效,两个无效。

所以错误信息应该是一个,但结果是两个!!

有人可以帮忙解决这个问题吗?

这里是run file

这是地址html和ts文件

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

@Component({
    moduleId: module.id,
    selector: 'address',
    templateUrl: 'address.component.html',
})
export class AddressComponent {
    @Input('group')
    public adressForm: FormGroup;
}
<div [formGroup]="adressForm">
    <div class="form-group col-xs-6">
        <label>street</label>
        <input type="text" class="form-control" formControlName="street">
        <small [hidden]="adressForm.controls.street.valid" class="text-danger">
            Street is required
        </small>
    </div>
    <div class="form-group col-xs-6">
        <label>postcode</label>
        <input type="text" class="form-control" formControlName="postcode">
    </div>
</div>

这是应用

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormArray, FormBuilder, Validators } from '@angular/forms';
import { Customer } from '../model/customer.model';

@Component({
    selector: 'customer-component',
    templateUrl: 'customer.component.html',
})
export class CustomerComponent implements OnInit {
    public customerForm: FormGroup;

    constructor(private _fb: FormBuilder) { }

    ngOnInit() {
        this.customerForm = this._fb.group({
            'name': ['', [Validators.required, Validators.minLength(5)]],
            'addresses': this._fb.array([])
        });

        // add address
        this.addAddress();

        this.customerForm.valueChanges
            .subscribe(data => this.onValueChanged(data));

        this.onValueChanged(); // (re)set validation messages now
    }

    initAddress() {
        return this._fb.group({
            'street': ['', Validators.required],
            'postcode': ['']
        });
    }

    addAddress() {
        const control = <FormArray>this.customerForm.controls['addresses'];
        const addrCtrl = this.initAddress();

        control.push(addrCtrl);

    }

    removeAddress(i: number) {
        const control = <FormArray>this.customerForm.controls['addresses'];
        control.removeAt(i);
    }

    onSubmit() {

    }

    onValueChanged(data?: any) {

        const form = this.customerForm;

        for (const field in this.formErrors) {
            // clear previous error message (if any)

            const control = form.get(field);

            if (control instanceof FormArray) {

                const fmArray = <FormArray>control;
                console.log("from Array have count : " + fmArray.controls.length);
                this.formErrors[field] = [];

                fmArray.controls.forEach(g => this.formErrors[field].push(this.addressErrors));

                let groupIndex = 0;
                for (const groupItem of fmArray.controls) {
                    const group = <FormGroup>groupItem;

                    console.log("group index is here == " + groupIndex);

                    for (const ctrlField in this.addressErrors) {
                        const gpControl = group.controls[ctrlField];

                        this.formErrors[field][groupIndex][ctrlField] = '';

                        if (gpControl && gpControl.dirty && !gpControl.valid) {
                            const messages = this.validationMessages[ctrlField];
                            for (const key in gpControl.errors) {
                                console.log("control error key is here ==" + key);
                                this.formErrors[field][groupIndex][ctrlField] += messages[key] + ' ';

                                console.log("set value on object of key is here ==" + ctrlField)
                                console.log(this.formErrors[field][groupIndex]);
                            }
                        }

                    }
                    groupIndex++;
                }

            }
            else {
                this.formErrors[field] = '';
                if (control && control.dirty && !control.valid) {
                    const messages = this.validationMessages[field];
                    for (const key in control.errors) {
                        this.formErrors[field] += messages[key] + ' ';
                    }
                }
            }

        }
    }

    formErrors: any = {
        'name': '',
        'addresses': []
    };

    addressErrors: any = {
        'street': ''
    }

    validationMessages: any = {
        'name': {
            'required': 'Name is required.',
            'minlength': 'Name must be at least 4 characters long.'
        },
        'street': {
            'required': 'Street is required.',
        }
    };
}
<h1>
    Customer Dynamic Static Form Reactive</h1>
<form [formGroup]="customerForm" (ngSubmit)="onSubmit()">
    <div class="form-group">
        <label for="name">Name</label>

        <input type="text" id="name" class="form-control" formControlName="name">

        <div *ngIf="formErrors.name" class="alert alert-danger">
            {{ formErrors.name }}
        </div>
    </div>

    <!--addresses-->
    <div formArrayName="addresses">
        <div *ngFor="let address of customerForm.controls.addresses.controls; let i=index" class="panel panel-default">
            <div class="panel-heading">
                <span>Address {{i + 1}}</span>
                <span class="glyphicon glyphicon-remove pull-right" *ngIf="customerForm.controls.addresses.controls.length > 1" (click)="removeAddress(i)"></span>
            </div>
            <div class="panel-body" [formGroupName]="i">
                <address [group]="address"></address>
            </div>
        </div>
    </div>

    <div class="margin-20">
        <a (click)="addAddress()" style="cursor: default"> Add another address +
</a>
</div>

<div class="margin-20">
    <button type="submit" class="btn btn-primary pull-right" [disabled]="!customerForm.valid">Submit</button>
</div>
<div class="clearfix"></div>


<div class="margin-20">
    <pre>formErrors: <br>{{formErrors  | json}}</pre>
    <div>myForm details:-</div>
    <pre>Is myForm valid?: <br>{{customerForm.valid | json}}</pre>
    <pre>form value: <br>{{customerForm.value | json}}</pre>
</div>
</form>

html 和 ts 文件

您是否尝试过采用 Angular 文档中概述的 onValueChanged 方法?

onValueChanged(data?: any) {
  if (!this.heroForm) { return; }
  const form = this.heroForm.form;

  for (const field in this.formErrors) {
    // clear previous error message (if any)
    this.formErrors[field] = '';
    const control = form.get(field);

    if (control && control.dirty && !control.valid) {
      const messages = this.validationMessages[field];
      for (const key in control.errors) {
        this.formErrors[field] += messages[key] + ' ';
      }
    }
  }
}

formErrors = {
  'name': '',
  'power': ''
};