angular 6 warning for using formControlName and ngModel
AngularAngular NgmodelAngular Reactive-FormsAngular Problem Overview
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.
Angular Solutions
Solution 1 - Angular
Now you can find the documentation here:
https://angular.io/api/forms/FormControlName#use-with-ngmodel-is-deprecated
So you have 3 options:
-
use Reactive forms
-
use Template driven forms
-
silence warning (not recommended)
<!-- language: lang-ts -->
imports: [
ReactiveFormsModule.withConfig({warnOnNgModelWithFormControl: 'never'});
]
Solution 2 - Angular
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
Solution 3 - Angular
add
[ngModelOptions]="{standalone: true}"
You can read more from angular website https://angular.io/api/forms/NgModel
Solution 4 - Angular
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:
-
Constructor:
this.assignedToFormGroup.controls['assignTo'].setValue({photoUrl: '', userName: ''});
-
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.
Solution 5 - Angular
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);