使用 formControlName 和 ngModel 的角度 6 警告

Posted

技术标签:

【中文标题】使用 formControlName 和 ngModel 的角度 6 警告【英文标题】:angular 6 warning for using formControlName and ngModel 【发布时间】:2018-09-29 19:19:33 【问题描述】:

我最近将 angular 版本升级到 6-rc。我收到以下警告

看起来您在同一个表单字段上使用 ngModel 窗体控件名称。支持使用 ngModel 输入属性和 带有响应式表单指令的 ngModelChange 事件已被弃用 在 Angular v6 中,将在 Angular v7 中删除

有关这方面的更多信息,请在此处查看我们的 API 文档: https://angular.io/api/forms/FormControlName#use-with-ngmodel

它到底说了什么?该链接没有#use-with-ngmodel的任何片段

我想我需要删除 ngModel 并使用 formGroup 作为我的数据绑定对象。

【问题讨论】:

你需要去next文档:next.angular.io/api/forms/FormControlName#use-with-ngmodel;虽然 v6 处于候选版本中,但文档仍然引用 v5。 我们将ngModel 用于数据,formControl 用于验证。 @Akshay 我们做了同样的事情。将整个应用程序更改为从反应式表单控件手动获取/设置值似乎是一项艰巨的工作。 在 Angular 6 响应式表单中没有 getter/setter 的快捷方式,就像在 C#.net 中一样,比如“string _myProperty get; set; ”?如果您在一种形式中有大量输入,您的代码会不会变得难以阅读? 我们所有使用 Angular 的人都越来越完全地脱离了真实的网络编程世界。 【参考方案1】:

如果您现在正在寻找 Angular 6 文档,请使用 https://next.angular.io

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

所以你有 3 个选择:

    使用响应式表单

    使用模板驱动的表单

    静音警告(不推荐)

    imports: [
      ReactiveFormsModule.withConfig(warnOnNgModelWithFormControl: 'never');
    ]
    

【讨论】:

天哪。改变语法和一直有效的东西有什么意义?我花了一天时间升级到 Angular 6 才发现这个。我注意到我的 onchange 选择事件没有触发。这是因为他们将这该死的语法从 onChange 更改为 selectionChange。真的很有用。 还有更多:对于常见的输入(文本、文本区域、选择、复选框等),现在,Angular 通过响应式表单配置禁用(ing)强制 ...很好...你不能使用一直使用的disabled=true。最糟糕的是:如果你制作自己的 ui-components 库......Angular 可能不知道什么是禁用......很好...... 对于一个正在开发的全新应用,您会推荐以上 3 种替代方案中的哪一种? @Stephane 我建议使用反应式表单 如何在没有 ngmodel 的情况下获得反应形式的价值【参考方案2】:

从 formGroup 中包含 formControlName 的每个字段中删除 [(ngModel)] 并在控制器类中设置值,如下简单 this.form.get('first').setValue('some value'); 不要关闭或显式静音警告

【讨论】:

是的,但为了更好地理解,我从 Angular 文档中编写了一段代码 感谢您尝试提高阅读和理解文档的示例 那么你如何在没有 ngmodel 的情况下获得价值 @Flash, this.form.get('fieldName').value【参考方案3】:

添加

[ngModelOptions]="standalone: true" 

您可以从 Angular 网站 https://angular.io/api/forms/NgModel 阅读更多内容

【讨论】:

我认为很多人对 Angular 弃用支持 ngModel 以与 formControlName 一起使用而不是完全弃用 ngModel 的事实感到困惑。 这是否意味着模板驱动的表单将消失,人们应该改用反应式表单?【参考方案4】:

所以我在尝试在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"  />
    <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"  />
    <span>@user.userName</span>
  </mat-option>
</mat-select>

在控制器中,formGroup 是这样定义的:

public assignedToFormGroup: FormGroup;

我听从了 Sohail 的建议,并从我的 html 代码中删除了 [(ngModel)]

<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"  />
    <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"  />
    <span>@user.userName</span>
  </mat-option>
</mat-select>

打开页面时出现错误 - 我尝试从 null 加载 photoUrl 和 userName,因为通过删除 [(ngModel)] 我还删除了 mat-select 中的默认选择。

所以我修改了我的控制器以执行以下操作: 1.构造函数:

this.assignedToFormGroup.controls['assignTo'].setValue(photoUrl: '', userName: '');

    我保存表单的按钮操作 - 添加了以下行:

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

这确实有效。现在我在页面加载时设置默认选择并在提交表单时读取选定的值。 我知道这不是最好和最漂亮的解决方案,但我想我会分享它 - 可能是更好的解决方案的一个很好的起点。

【讨论】:

【参考方案5】:

结合 Rxjs 使用 formControl(reactive Forms) 更直接,因此 Angular 团队改变了使用它。

修改html文件

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

[formControl]="myControl"

修改ts文件

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

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

this.myControl.valueChanges.pipe(
      .subscribe(model => this.postErrorMessage = model);

【讨论】:

以上是关于使用 formControlName 和 ngModel 的角度 6 警告的主要内容,如果未能解决你的问题,请参考以下文章

带有 ControlValueAccessor 和 formControlName 的 Angular Material Datepicker [重复]

在Angular2中将管道添加到formControlName

以角度与 FormControlName 绑定

formControlName 必须与父 formGroup 指令一起使用

Angular 2 - 组件内的 formControlName

Angular 8:组件内部的formControlName下面有多个嵌套级别