0

I'm new to Angular2 (or 4?), working my way through the fundamentals..
In the Forms/Reactive Forms - an array of addresses are added with no problem.

However trying to add validators to the address sub-elements doesn't work:
Here's my form building:

constructor(
    private fb: FormBuilder
    ){
    this.createForm();
    }

createForm() {
    this.heroForm = this.fb.group({
        name: ['', [Validators.required, Validators.minLength(6)]],
        secretLairs: this.fb.array([
            this.fb.group({
                street: ['', [Validators.required, Validators.minLength(6)]],
                city:   [''],
                state:  ['', Validators.required],
                zip:    ['']
            })
        ]),
        power: ['',Validators.required],
        sidekick: ''
    });
}

get secretLairs(): FormArray {
    return this.heroForm.get('secretLairs') as FormArray;
}

And (part of) my template:

<div formArrayName="secretLairs" class="well well-lg">
    <b class=header>Secret Lairs</b>
    <div *ngFor="let address of secretLairs.controls; let i=index" [formGroupName]="i" >

{{ showMe(i, address.controls.street) }}

        <h4>Address #{{i + 1}}</h4>
        <div style="margin-left: 1em;">
            <div class="form-group">

                <label class="center-block">Street:</label>
                <input class="form-control" trim formControlName="street">

                <label class="center-block">City:</label>
                <input class="form-control" formControlName="city">

                <label class="center-block">State:</label>
                <select class="form-control" formControlName="state">
                    <option *ngFor="let state of states" [value]="state">{{state}}</option>
                </select>

                <label class="center-block">Zip Code:</label>
                <input class="form-control" formControlName="zip">

            </div>
        </div>
        <br>
    </div>
    <button (click)="addLair()" type="button">Add a Secret Lair</button>
</div>

The ShowMe function: console.logs the street-formControl
- which shows null in both validator and asyncValidator..?
And indeed no (in)validation takes place for the address-elements
- the other validators (and everything else) works perfectly.

What am I missing ?

4
  • Can you try with Validator.compose on your street items. Validators.compose([]) and new FormControl: street: new FormControl('', Validators.compose(Validators.required, Validators.minLength(6))) etc. Commented Aug 22, 2017 at 12:52
  • Nope => street: new FormControl('', Validators.required) => Makes no difference: validator:null - and an empty street-field is still ng-valid. Also tried the compose( double ) - no validator..? Commented Aug 22, 2017 at 13:11
  • All works fine plnkr.co/edit/RpcfJZSZToF5UWoKzdLh?p=preview Try typing in Street field Commented Aug 22, 2017 at 14:37
  • @yurzui - Yep. My problem was: When getting the data (ngOnChanges), I replaced the formArray with a new one where the controls contained only the values - no validators : ( "auto-created" with addresses.map(address => this.fb.group(address)) Commented Aug 22, 2017 at 14:49

1 Answer 1

1

Got it - I was overwriting the formArray when new data arrived (ngOnChanges):

setAddresses(addresses: Address[]) {
  const addressFGs = addresses.map(address => this.fb.group(address));
  const addressFormArray = this.fb.array(addressFGs);
  this.heroForm.setControl('secretLairs', addressFormArray);
}

this.fb.group(address) created 4 new formControls with only (default) values - no validators.

Alternative:

createForm() {
    this.heroForm = this.fb.group({
        name:       ['', [Validators.required, Validators.minLength(6)]],
        secretLairs: this.fb.array([]),                         // no controls yet
        power:      ['',Validators.required],
        sidekick:    ''
    });
}

setAddresses(addresses: Address[]) {
    this.heroForm.setControl('secretLairs', new FormArray([])); // rough reset!
    addresses.map( address => this.addLair(address));
}

addLair(adr) {
    this.secretLairs.push(this.fb.group({
        street: [(adr)?adr.street:'', [Validators.required, Validators.minLength(4)] ],
        city:    (adr)?adr.city  :'',
        state:  [(adr)?adr.state :'', Validators.required],
        zip:     (adr)?adr.zip   :''
        }
    ));
}

get secretLairs(): FormArray {
    return this.heroForm.get('secretLairs') as FormArray;
}

The addLair() is also used by a button to append a new address (no adr parameter)
- So I can keep the address-form-building in one place : )

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.