61

I recently upgraded the angular version to 6-rc. I got following warning

It looks like you're using ngModel on the same form field as formControlName. Support for using the ngModel input property and ngModelChange event with reactive form directives has been deprecated in Angular v6 and will be removed in Angular v7

For more information on this, see our API docs here: https://angular.io/api/forms/FormControlName#use-with-ngmodel

What does it say exactly? the link does not have any fragment for #use-with-ngmodel

I guess I need to remove ngModel and use formGroup as my data binding object.

Akshay
  • 3,558
  • 4
  • 43
  • 77
  • You need to go to the `next` docs: https://next.angular.io/api/forms/FormControlName#use-with-ngmodel; while v6 is in release candidate the docs still refer to v5. – jonrsharpe Apr 19 '18 at 10:19
  • Curiosity: Why do you want use [(ngModel)] and formControlName in the same input tag? – Eliseo Apr 19 '18 at 10:47
  • I have started using ngModel from angular 2 beta then added formControl. Now couldn't change this for many forms – Akshay Apr 19 '18 at 11:28
  • 23
    We used `ngModel` for data and `formControl` for validation. – Akshay Apr 19 '18 at 13:16
  • 8
    @Akshay We did the same thing. It seems too big of a job to change the whole app to manually get/set values from reactive form controls. – umutesen May 11 '18 at 19:56
  • 1
    Aren't there any shortcut for getter/setter in Angular 6 reactive forms just like in C#.net like this "string _myProperty { get; set; }"? If you have a lot of inputs in one form wouldn't your code become too hard to read? – Sherwin Ablaña Dapito May 18 '18 at 03:04
  • 1
    All of us who work with Angular are geting more and more completely out of the real, web programing World. – Pedro Ferreira Sep 08 '18 at 01:14

6 Answers6

54

Now you can find the documentation here:

https://angular.io/api/forms/FormControlName#use-with-ngmodel-is-deprecated

So you have 3 options:

  1. use Reactive forms

  2. use Template driven forms

  3. silence warning (not recommended)

<!-- language: lang-ts -->

    imports: [
      ReactiveFormsModule.withConfig({warnOnNgModelWithFormControl: 'never'});
    ]
Marcus
  • 1,857
  • 4
  • 22
  • 44
yurzui
  • 205,937
  • 32
  • 433
  • 399
  • 49
    Oh my god. What's the point of changing syntax and things that work all the time? I spent like a day upgrading to Angular 6 to now find this. I noticed my onchange selection events weren't firing. It was because they changed the freaking syntax from `onChange` to `selectionChange`. Really useful. – Luis Lavieri Aug 07 '18 at 16:38
  • 4
    And there's more: for common inputs (text, textarea, select, checkbox, etc.), now, Angular does the disable(ing) *mandatory* through the Reactive Form config... nice... you can not use all-time-used *disabled=true*. And worst: if you make your own ui-components library... Angular might not have a clue of what is *disabled*... nice.... – Pedro Ferreira Sep 08 '18 at 01:16
  • 1
    For a brand new app in the making, which of the above 3 alternatives would you recommend ? – Stephane Oct 14 '18 at 16:41
  • 7
    @Stephane I would recommend using reactive forms – yurzui Oct 14 '18 at 17:54
  • 4
    how do you get the value in reactive forms without ngmodel – Flash Jan 22 '20 at 16:13
  • if they remove it in angular 7, what will be the counter part? thanks – Jenuel Ganawed Aug 05 '20 at 03:47
29

Remove [(ngModel)] from every field within formGroup contains formControlName and set value in controller class as follows simply this.form.get('first').setValue('some value'); do not close or silence warnings explicitly

Sohail Anwar
  • 349
  • 3
  • 12
4

add

[ngModelOptions]="{standalone: true}" 

You can read more from angular website https://angular.io/api/forms/NgModel

Nick
  • 138,499
  • 22
  • 57
  • 95
  • 4
    I think a lot of people are confused with the fact that Angular is deprecating support for `ngModel` to work with `formControlName` rather than completely deprecating `ngModel`. – Nikhil Jan 04 '19 at 12:57
  • does this mean template driven forms will be gone and people should use reactive forms instead? – chitgoks Oct 03 '19 at 03:43
0

So I stumbled upon this when trying to display users' avatars in mat-select:

<mat-form-field [formGroup]="assignedToFormGroup">
<mat-select placeholder="Assign to" [(ngModel)]="assignedTo" formControlName="assignTo">
  <mat-select-trigger>
    <img style="vertical-align:middle;" aria-hidden
      src="{{assignedToFormGroup.controls['assignTo'].value.photoUrl}}" height="20" />
    <span>@{{assignedToFormGroup.controls['assignTo'].value.userName}}</span>
  </mat-select-trigger>
  <!-- {{user.userName}} -->
  <mat-option *ngFor="let user of members" [value]="user">
    <img style="vertical-align:middle;" aria-hidden src="{{user.photoUrl}}" height="20" />
    <span>@{{user.userName}}</span>
  </mat-option>
</mat-select>

In controller, the formGroup was defined this way:

public assignedToFormGroup: FormGroup;

I followed Sohail's advice and removed [(ngModel)] from my HTML code:

<mat-form-field [formGroup]="assignedToFormGroup">
<mat-select placeholder="Assign to" formControlName="assignTo">
  <mat-select-trigger>
    <img style="vertical-align:middle;" aria-hidden
      src="{{assignedToFormGroup.controls['assignTo'].value.photoUrl}}" height="20" />
    <span>@{{assignedToFormGroup.controls['assignTo'].value.userName}}</span>
  </mat-select-trigger>
  <!-- {{user.userName}} -->
  <mat-option *ngFor="let user of members" [value]="user">
    <img style="vertical-align:middle;" aria-hidden src="{{user.photoUrl}}" height="20" />
    <span>@{{user.userName}}</span>
  </mat-option>
</mat-select>

That gave me errors when opening page - I tried to load photoUrl and userName from null, because by removing [(ngModel)] I also removed default selection in mat-select.

So I modified my controller to do the following: 1. Constructor:

this.assignedToFormGroup.controls['assignTo'].setValue({photoUrl: '', userName: ''});
  1. Button action where I save my form - added following line:

    let assignedTo = this.assignedToFormGroup.controls['assignTo'].value;

That actually worked. Now I'm setting default selection on page load and read selected value when submitting the form. I'm aware that it's not the best and prettiest solution, but I thought I'll share it - might be a good starting point for better solution.

greenskin
  • 544
  • 8
  • 22
0

I had the same warning when I use [(ngMode)] together with [formControlName] in an embedded custom control. My form is built dynamicly using formBuilder.array([]) and I have to stay with [formControlName]:

this.searchForm = this.formBuilder.group({
      dynamicFormArray: this.formBuilder.array([])
});

But after I removed [(ngMode)] which is two-way bounding, I can no longer get the user input value from the embedded custom control using form.value (though I can see the value inside the embedded control)!

After painful strugging for some time, I've finally found a solution to make the user input value from the embedded contorl available to form.value. The key is to use patchValue for the dyanmicFormArray (not the form itself or formBuilder.group!):

this.dynamicFormArray.patchValue([{name: this.value}]);

Hope this could help some friends with similar issue.

David W
  • 31
  • 3
-2

Using formControl(reactive Forms) is more straightforward coupled with Rxjs so Angular team changed use of it.

Change on html file

<!-- [ngModel]='model' (ngModelChange)='changed($event)' -->

to

[formControl]="myControl"

Change ts file

model: string;
  modelChanged: Subject<string> = new Subject<string>();

  changed(text: string) {
      this.modelChanged.next(text);
  }
  this.modelChanged.pipe(
      .subscribe(model => this.postErrorMessage = model);

to

this.myControl.valueChanges.pipe(
      .subscribe(model => this.postErrorMessage = model);
Ahmet Arslan
  • 5,380
  • 2
  • 33
  • 35