subscribe to valueChanges from input FormControl in FormGroup

Angular

Angular Problem Overview


In Angular 4, I'm trying to subscribe to the valueChanges of a FormControl. Neither of the versions below is working. I'm not seeing any errors. The form.value JSON is updating as I type, but the subscription isn't working.

myForm: FormGroup;
public firstName = new FormControl();
public lastName = new FormControl();

this.myForm = this.formBuilder.group({ 
      firstName: '',
      lastName: '',
});

this.myForm.controls.firstName.valueChanges.subscribe(value => {
      console.log(value);
});

    
this.myForm.get('firstName').valueChanges.subscribe(value => {
      console.log('name has changed:', value)
});

Here's a template snippet.

<form #myForm="ngForm">

<md-input-container>
    <input mdInput name="firstName" [(ngModel)]="firstName" placeholder="enter name"/>
</md-input-container>
               

{{ myForm.value | json }}

Angular Solutions


Solution 1 - Angular

I think you are missing some thing here with formGroup and formControlName you should do:

myForm: FormGroup;
firstName = '';
lastName = '';

on ngOnInit

this.myForm = this.formBuilder.group({
    firstName: [this.firstName],
    lastName: [this.lastName]
});

this.myForm.controls['firstName'].valueChanges.subscribe(value => {
  console.log(value);
});

and In HTML

<form [formGroup]="myForm">
   ...

  <input name="firstName" [(ngModel)]="firstName" formControlName="firstName" placeholder="enter name"/>


  <input name="lastName" [(ngModel)]="lastName" formControlName="lastName" placeholder="enter last name"/>

   ...
</form>

Solution 2 - Angular

You are missing some crucial things in your code. First of all, what you are trying to subscribe to, doesn't exist. You have not marked that field to be a formcontrol, so Angular doesn't know to subscribe to that. You need to mark formControlName="firstname" to let Angular know it's a form control.

Also you are missing marking your form as a form group, it should be:

<form [formGroup]="myForm">

Using ngModel in forms is discouraged, the ngModel directive isn't even included in ReactiveFormsModule. I have also noticed that it often causes issues when used together with reactive forms. You have the form controls there to replace the use of ngModel, so drop it and make use of the form controls, since they are already in place! :)

Then I would instead of using valueChanges just use some change event instead in the template, but it's up to you.

So, the build of the form should look like this:

this.myForm = this.formBuilder.group({
  firstname: [''],
  lastname: ['']
})
// I like to use variables
this.firstNameCtrl = this.myForm.get('firstname')

// as mentioned, like to use change event:
logValue(value) {
  console.log(value)
}    

The template would then look like this:

<form [formGroup]="myForm">
  <md-input-container>
    <input mdInput formControlName="firstname" 
         (keyup)="logValue(firstNameCtrl.value)" />
  </md-input-container>  
  <md-input-container>
    <input mdInput formControlName="lastname"/>
  </md-input-container>   
</form>

So as mentioned use the form controls. If you need an initial value, set them in the build of the form. You have all values in your form object and you can access the values if you wish.

Solution 3 - Angular

I gave up on FormGroup and FormBuilder and just used

HTML:

<input mdInput [formControl]="firstName"> 

App class:

firstName = new FormControl();

ngOnInit:

this.firstName.valueChanges.subscribe(value => {
     console.log('name has changed:', value)
});

My test is currently broken with the error "No provider for NgControl" but I'll work on that next. Update: I just needed to import ReactiveFormsModule in the TestBed

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbeachCodeView Question on Stackoverflow
Solution 1 - AngularTouqeer ShafiView Answer on Stackoverflow
Solution 2 - AngularAT82View Answer on Stackoverflow
Solution 3 - AngularbeachCodeView Answer on Stackoverflow