how to reactive validation messages in dynamic forms in angular 2
<p>I am learning reactive dynamic forms in angular 2.</p>

<p>I want to validation messages like angular.io cookbook form-validation does.</p>

<p>Something like this:</p>

<pre><code> this.heroForm.valueChanges
  .subscribe(data =&gt; this.onValueChanged(data));
</code></pre>

<p>So I subscribe form valuechanges in dynamic forms</p>

<p>but strange thing is happen， something like:</p>

<p>I have two addrees from group, one is valid, two is invalid.</p>

<p>So error message should be one, but the result is both!!</p>

<p>would someone help fix this?</p>

<p>here is <a href="https://plnkr.co/edit/clTbNP7MHBbBbrUp20vr?p=info" rel="nofollow noreferrer">run file</a></p>

<p>Here is adress html and ts file</p>

<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>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;
}</code></pre>
<pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;div [formGroup]="adressForm"&gt;
    &lt;div class="form-group col-xs-6"&gt;
        &lt;label&gt;street&lt;/label&gt;
        &lt;input type="text" class="form-control" formControlName="street"&gt;
        &lt;small [hidden]="adressForm.controls.street.valid" class="text-danger"&gt;
            Street is required
        &lt;/small&gt;
    &lt;/div&gt;
    &lt;div class="form-group col-xs-6"&gt;
        &lt;label&gt;postcode&lt;/label&gt;
        &lt;input type="text" class="form-control" formControlName="postcode"&gt;
    &lt;/div&gt;
&lt;/div&gt;</code></pre>
</div>
</div>
</p>

<p>Here is app </p>

<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>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 =&gt; this.onValueChanged(data));

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

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

    addAddress() {
        const control = &lt;FormArray&gt;this.customerForm.controls['addresses'];
        const addrCtrl = this.initAddress();

        control.push(addrCtrl);

    }

    removeAddress(i: number) {
        const control = &lt;FormArray&gt;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 = &lt;FormArray&gt;control;
                console.log("from Array have count : " + fmArray.controls.length);
                this.formErrors[field] = [];

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

                let groupIndex = 0;
                for (const groupItem of fmArray.controls) {
                    const group = &lt;FormGroup&gt;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 &amp;&amp; gpControl.dirty &amp;&amp; !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 &amp;&amp; control.dirty &amp;&amp; !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.',
        }
    };
}</code></pre>
<pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;h1&gt;
    Customer Dynamic Static Form Reactive&lt;/h1&gt;
&lt;form [formGroup]="customerForm" (ngSubmit)="onSubmit()"&gt;
    &lt;div class="form-group"&gt;
        &lt;label for="name"&gt;Name&lt;/label&gt;

        &lt;input type="text" id="name" class="form-control" formControlName="name"&gt;

        &lt;div *ngIf="formErrors.name" class="alert alert-danger"&gt;
            {{ formErrors.name }}
        &lt;/div&gt;
    &lt;/div&gt;

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

    &lt;div class="margin-20"&gt;
        &lt;a (click)="addAddress()" style="cursor: default"&gt; Add another address +
&lt;/a&gt;
&lt;/div&gt;

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


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

<p>html and ts file</p>