Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular - formGroupName value change does not update the form

As described in the title, formGroupName value change does not update the form. (after hitting the button the value displayed in the input remains the same)

Here is a plunker.

@Component({
  selector: 'my-app',
  template: `
   <form [formGroup]="myForm">
    <div [formGroupName]="fgn">
        <input [formControlName]="'name'">
    </div>
</form>

<button (click)="formChange()" >Change</button>

{{fgn}}
<br>
{{myForm.value | json}}
  `,
})
export class App {

    private myForm: FormGroup;
    private fgn: String;

    ngOnInit() {
        this.fgn = 'zero';

        this.myForm = this.formBuilder.group({
            zero: this.formBuilder.group({
                name: 'Zero'
            }),
            one: this.formBuilder.group({
                name: 'One'
            })
        });
    }

    formChange() {
        this.fgn = 'one';
    }

    constructor(private formBuilder: FormBuilder) {

    }
}
like image 912
Thodoris Avatar asked Jan 08 '18 13:01

Thodoris


3 Answers

I would recommend like instead of using,

<input [formControl]="myForm.controls[fgn].controls['name']">

use,

<form [formGroup]="myForm">
 <div [formGroup]="myForm.controls[fgn]">
  <input [formControlName]="'name'">
 </div>
</form>

The reason is, if you have n number of input fields, for example, more than 25 fields in a form, it is not a good practice to apply [formControl]="myForm.controls[fgn].controls['name']" kind of declaration in each field as this will take more time and looks like a nightmare if you want to modify any simple changes.

Instead, if you use [formGroup]="myForm.controls[fgn]", it will take care of the inner [formControlName] by itself. And this works well as I'm using it in my project.

Thanks to @Amit for initiating this idea in me.

Hope this helps. Happy optimized coding :)

like image 164
Venkatesh Rajavetrivel Avatar answered Nov 03 '22 01:11

Venkatesh Rajavetrivel


You were doing wrong. Correct code will be :

<form [formGroup]="myForm">
    <div>
        <input [formControl]="myForm.controls['zero'].controls['name']">
        {{myForm.controls['zero'].controls['name'].value}}
    </div>
</form>

<button (click)="formChange()" >Change</button>

{{fgn}}
<br>
{{myForm.value | json}}

Explanation

formControlName expects name of form control but you were using in a wrong way => [formControlName]. When you are passing a form control object rather than name of form control then you use [formControl]. Hope this will help

like image 30
Sandip Jaiswal Avatar answered Nov 03 '22 02:11

Sandip Jaiswal


Not sure why it didn't work with the formControlName approach.

This seems to work though:

<input [formControl]="myForm.controls[fgn].controls['name']">

UPDATE:

You could use this workaround for AOT:

<input [formControl]="myForm.get(fgn + '.name')" />

(This is considered a workaround since this invokes the get method way too often)

like image 38
Amit Avatar answered Nov 03 '22 00:11

Amit