87

https://angular.io/api/forms/FormGroup#controls

Follwing my form:

this.form= this.fb.group({
  id: ['', [Validators.required]],
  name: ['', [Validators.maxLength(500)]],
  child: this.fb.group({
    id: [ '', [Validators.required]],
    name: ['']
  })
});

I want to get the validity of child, like this.form.controls.child.controls.valid, while .controls renturn AbstractControl refer to this formgroup api.

angular compile error, error TS2339: Property 'controls' does not exist on type 'AbstractControl'.

6 Answers 6

161

You are close. See code example below or play with it on the very simple (and ugly) StackBlitz I created.

StackBlitz Demo

In your template be sure to add your child form group.

<div>
  <form [formGroup]="myForm" (ngSubmit)="send()">
    <input type="text" name="name" formControlName="name">
    <div formGroupName="child">
       <input type="text" name="id" formControlName="id">
       <input type="text" name="name" formControlName="name">
    </div>
    <button class="btn btn-primary">send</button>
  </form>
</div>

Then in your component you can access the fields like so.

this.myForm['controls'].child['controls'].id.valid

The reactive form I created for this example:

this.myForm = this.fb.group({
      name: ['', [Validators.maxLength(500)]],
      child: this.fb.group({
        id: ['', [Validators.required]],
        name: ['']
      })
    });

**Update Dec 2019**

My original answer is a bit dated. There is now a much cleaner way of accomplishing this! Below is example code of the cleaner solution.

this.myForm.get('child.id').valid

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

9 Comments

Thanks,my template is the same as yours.I can get the controls of child in chrome, while compile error in ide. error TS2339: Property 'controls' does not exist on type 'AbstractControl'.
Ah yes, that is a nasty Angular bug. see updated answer, use this.myForm['controls'].child['controls'].id.valid instead
Great!You are right.Then I found another way to solve the qestion , convert this.form.controls.child's type to FormGroup.
Awesome, glad that worked. Also, that is a slick solution too! You should update your question to be more specific about the error you were needing to solve so anyone else running into your problem will find the solution. It’s a bit vague the way it’s written now and it is a very valid question.
how to perform setvalidators function to those nested formgroup items.
|
30

There are a couple of very simple ways to access the FormControl in a nested FormGroup. From the AbstractControl usage notes:

Retrieve a nested control

For example, to get a name control nested within a person sub-group:

this.form.get('person.name');

-OR-

this.form.get(['person', 'name']);

1 Comment

Link to the Angular docs for reference: angular.io/api/forms/AbstractControl#get
13
userForm=new FormGroup({
    fName:new FormControl('',Validators.required),
    lName:new FormControl(),
    eMail:new FormControl('',[Validators.email,Validators.required]),
    qualificationForm:new FormGroup({
     perS:new FormControl(''),
     perHs:new FormControl('')
    })
});

save(){
  console.log(this.userForm.get("qualificationForm.perS").value);
}

Comments

9

One way I use alot is to cast the child FormGroup to a FormGroup as the 'get('control')' method returns an AbstractControl and then use the 'get()' method to access the child FormGroup options like so :

(this.form.get('child') as FormGroup).get('id').valid

Comments

7

I have the following form:

registerLibrarianForm = this.formBuilder.group({
       firstName: ['', [Validators.required, Validators.minLength(2), Validators.maxLength(128), Validators.pattern(this.nameRegex)]],
       lastName:  ['', [Validators.required, Validators.minLength(2), Validators.maxLength(128), Validators.pattern(this.nameRegex)]],
       address: this.formBuilder.group({
         country: ['', [Validators.required]],
         city: ['', [Validators.required]]})})

The way I get the controls of the main form (registerForm) is by creating a simple return method:

get controls(){
return this.registerForm.controls;
}

And the way I get the controls of the nested form (address) is by creating another method:

get addressControls(){
return ((this.registerForm.get('address') as FormGroup).controls)
}

So if you need to do a *ngIf in the HTML for the main form use first method

*ngIf="controls.firstName.errors && ...

And for the nested form:

*ngIf="addressControls.country.errors && ...

I hope this might help!

Comments

0

I don't know why, but sometimes the bindings for nested form groups gets really confused when you're using nested [formGroup] or formGroupName. Luckily, AbstactControl.get supports nesting, so you can make this little helper function to cast the result of .get to not be null:

group: UntypedFormGroup;
constructor(private readonly fb: FormBuilder) {
    this.group = this.fb.group({
      'user' : this.fb.group({
        'name': [''],
        'address': this.fb.group({
          'city': [''],
          'state': [''],
          'street': [''],
        })       
      })
    });
}

getControl(path: string) {
  return this.group.get(path) as FormControl;
}

and then bind to your form like this:

<form>
    <mat-form-field>
        <mat-label>Street</mat-label>
        <input matInput [formControl]="getControl('user.address.street')">
    </mat-form-field>
</form>

you can also access form arrays -> nested groups like so:


const array = this.fb.array([
    this.fb.group({
      'name': [''],
      'address': this.fb.group({
        'city': [''],
        'state': [''],
        'street': [''],     
    })
  })
])

array.get('0.address.city')

I see a lot of silly abstraction sitting on top of accessing form controls because no-one knows how powerful AbstactControl.get is. Let's clean all that crap up. Add "simplify control access logic" to you tech debt.

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.