将 Angular 8 应用程序迁移到 9 的奇怪问题

Posted

技术标签:

【中文标题】将 Angular 8 应用程序迁移到 9 的奇怪问题【英文标题】:strange problem migrating angular 8 app to 9 【发布时间】:2020-05-24 11:25:44 【问题描述】:

我正在将应用程序从 angular 8 迁移到 9。如果我尝试构建部署,我会收到此错误消息

ERROR : Cannot assign value "$event" to template variable "value". Template variables are read-only.
    at _AstToIrVisitor.visitPropertyWrite (...\node_modules\@angular\compiler\bundles\compiler.umd.js:8617:31)
    at PropertyWrite.visit (...\node_modules\@angular\compiler\bundles\compiler.umd.js:7459:28)
    at convertActionBinding (...\node_modules\@angular\compiler\bundles\compiler.umd.js:8224:49)
    at prepareEventListenerParameters (...\node_modules\@angular\compiler\bundles\compiler.umd.js:16861:27)
    at Object.params (...\node_modules\@angular\compiler\bundles\compiler.umd.js:17952:24)
    at ...\node_modules\@angular\compiler\bundles\compiler.umd.js:17725:94
    at Array.map (<anonymous>)
    at ...\node_modules\@angular\compiler\bundles\compiler.umd.js:17725:60
    at ...\node_modules\@angular\compiler\bundles\compiler.umd.js:17014:87
    at Array.map (<anonymous>)
    at TemplateDefinitionBuilder.buildTemplateFunction (...\node_modules\@angular\compiler\bundles\compiler.umd.js:17014:60)
    at ...\node_modules\@angular\compiler\bundles\compiler.umd.js:17558:60
    at ...\node_modules\@angular\compiler\bundles\compiler.umd.js:16992:81
    at Array.forEach (<anonymous>)
    at TemplateDefinitionBuilder.buildTemplateFunction (...\node_modules\@angular\compiler\bundles\compiler.umd.js:16992:37)
    at Object.compileComponentFromMetadata (...\node_modules\@angular\compiler\bundles\compiler.umd.js:18643:58)

我怎样才能发现问题发生了?

【问题讨论】:

更改变量名,不要使用同名的变量和模型。即:使用 #fieldhtml 和 [(ngModel)]="field" 【参考方案1】:

听起来你在某个地方有一些看起来像的 html

<input #value (click)="value = $event" />

input 是一些元素,(click) 是一些事件处理程序。 (我以输入和点击为例,错误信息并没有说明它们的实际含义)

尝试查看代码中使用模板变量(在本例中为#value)的所有位置,并尝试在事件处理程序中以某种方式将事件结果分配给它。

编辑:

这是否意味着您在运行开发环境时没有看到此错误?如果是这样,这是否意味着您的开发环境中没有aot编译?我认为 v9 现在默认将 aot 设置为 true。至少在我最近升级时对我有影响。

【讨论】:

我在运行 ng serve 时遇到了同样的问题。清理一切并重新安装所有pacakges,但我有同样的问题。在所有模板中,$event 只是在调用组件方法时用作参数。我想问题出在第三方组件中,但我不明白是哪一个 这个问题的解决方案有帮助吗:***.com/questions/48021581/… ? 我的代码中没有这种表达方式。我只是在组件方法调用中使用 $event 作为参数,如果我不升级到 angular 9,应用程序运行良好 你有很多使用$event的实例吗?太多无法在此处发布或尝试一一删除以查看问题是否消失?【参考方案2】:

终于解决了问题。 我发现将其添加到 tsconfig 的问题。 json

  "angularCompilerOptions": 
    "fullTemplateTypeCheck": true,
    "strictInjectionParameters": true
  

我不确定这是否会自动添加到新项目的 tsconfig.json 中,但我的项目中没有。 启用这些选项后,我能够在编译器日志中看到错误并解决它。

【讨论】:

这应该是标记的 anwser,因为它强制编译器发出实际问题。 200%,正是我的问题和他的解决方案【参考方案3】:

我的问题来自 Angular Material 中 mat-option 的错误使用。

在 Angular 8 中,这段代码很好:

<mat-select formControlName="qualityStatus" required (selectionChange)="onChangeQualityStatus($event)">
                    <mat-option *ngFor="let movement of allowedMovements" [(value)]="movement">
                        movement.qualityStatusDescription
                    </mat-option>
</mat-select>

但在 Angular 9 中,[(value)]="movement" 会抛出错误。此代码应为[value]="movement"。内部括号不正确,导致编译器说您正在分配给一个变量。 Angular 8 忽略了这个问题。

希望这对其他人有所帮助。

【讨论】:

【参考方案4】:

启用 AOT: angular.json >> 架构师 >> 构建 >> 选项 >> "aot":true

添加: “角编译器选项”: “fullTemplateTypeCheck”:真, “严格注入参数”:真 , 到 tsconfig.json

这样你应该可以看到错误在哪里

【讨论】:

如果您目前没有解决方案,最好添加评论。【参考方案5】:

代码替换一下

*ngFor="let movement of allowedMovements" [(value)]="movement" 

*ngFor="let movement of allowedMovements; let i = index" [(value)]="allowedMovements[i]"

【讨论】:

【参考方案6】:

正如其他人所说,“模板变量是只读的”是双向绑定

适用于角度 8

  [(ngModel)] 
  [(value)]

在角度 9 中引发错误

  [(ngModel)] 
  [(value)]

适用于角度 9

  [ngModel]
  (ngModel)
  [value]

在我的情况下,我错误地将 ngModel 放置在恰好有 $event 的 *ngFor 中

在角度 9 中引发错误

 <ng-container *ngFor="let color of palette; let i = index">
 <mat-form-field class="colorbtn">
   <input matInput type="color" [(value)]="color" 
    [(ngModel)]="color + i" (change)="Color($event, i)">
 </mat-form-field>
</ng-container>

适用于角度 9

<ng-container *ngFor="let color of palette; let i = index">
 <mat-form-field class="colorbtn">
   <input matInput type="color" [value]="color" (ngModel)="color + i" (change)="Color($event, i)">
 </mat-form-field>
</ng-container>

【讨论】:

是的。这解决了我的问题(Angular 11 版)【参考方案7】:

使用aot 编译以查看所有运行时错误

ng serve --aot

【讨论】:

【参考方案8】:
#userName="ngModel" name="userName" [(ngModel)]="userName"

#userName value with [(ngModel)]="userName" should not be same
id change property in component.ts to
modelUserName :strgin;

#userName="ngModel" name="userName" [(ngModel)]="modelUserName"

【讨论】:

【参考方案9】:

我收到此错误:

    <input id="inputPassword" name="inputPassword"
        [(ngModel)]="password" required #password="ngModel">

然后我用一个对象(或不同的名称)替换了密码变量,它解决了这个问题。

   <input id="inputPassword" name="inputPassword"
        [(ngModel)]="user.password" required #password="ngModel">

【讨论】:

【参考方案10】:

我使用 ngFor 进行下拉控制,升级到版本 Angular 9 时出现此错误。 问题是下拉选项不需要圆括号

之前 [(ngValue)]="listItem"

之后 [ngValue]="listItem"

【讨论】:

【参考方案11】:

我得到这个错误

<input id="DateOfBirth"
        type="text"
        #dateOfBirth
        name="DateOfBirth"
        class="form-control"
        bsDatepicker
        datePickerMomentModifier
        [(date)]="dateOfBirth"
        [(ngModel)]="model.dateOfBirth"
        [bsConfig]=" adaptivePosition: true "/>

然后我就这样解决了,在日期绑定中添加了模型。

 <input id="DateOfBirth"
        type="text"
        #dateOfBirth
        name="DateOfBirth"
        class="form-control"
        bsDatepicker
        datePickerMomentModifier
        [(date)]="model.dateOfBirth"
        [(ngModel)]="model.dateOfBirth"
        [bsConfig]=" adaptivePosition: true "/>

【讨论】:

【参考方案12】:

当组件将其输入之一传递给具有双向数据绑定的子组件时,我已经看到了这种情况。

public class MyComponent 
  @Input()
  public foo;


public class MyChildComponent 
  @Input()
  public bar;

<!-- Invalid -->
<my-child-component [(bar)="foo"/>

<!-- Valid -->
<my-child-component [bar]="foo"/>

输出绑定无效,因为 Angular 无法从组件内分配 foo 的值。如果 foo 需要更改,您需要在 MyComponent 之外发出一个事件来更改该值。

【讨论】:

【参考方案13】:

正如错误提示的那样,模板变量是只读的,因此您不能将模型绑定到模板变量,而是可以绑定到组件属性。

在我的例子中,使用 Angular 11,我将输入字段绑定到模板变量(即 [(ngModel)]="UserNameSearch")而不是组件属性,因为我的属性名称与模板变量相同。我将我的组件属性更改为驼峰式大小写并使用它来绑定并且它工作。

之前:[(ngModel)]="UserNameSearch"(绑定到模板变量)

之后:[(ngModel)]="userNameSearch"(绑定到组件属性)

【讨论】:

【参考方案14】:

确保您没有将 DOM 中的 HTML 元素命名为与 ngModel 引用相同的名称。

这会报错:

<select class="custom-select mr-sm-2" id="myVariable" name="myVariable" [(ngModel)]="myVariable" #myVariable="ngModel" required>

将 HTML DOM 中的元素更改为不同的东西为我解决了这个问题。

<select class="custom-select mr-sm-2" id="myVariableHtml" name="myVariableHtml" [(ngModel)]="myVariable" #myVariableHtml="ngModel" required>

【讨论】:

【参考方案15】:

不要同时使用 [(ngModel)]="password"#password。我遇到了同样的错误,只是修复了删除 #password

【讨论】:

这个解决方案以 Angular 12 形式为我解决了这个问题。我最终删除了 [(ngModel)]="password" 因为输入不接受来自那里的值。当它被传递给函数时,它确实接受了来自#password 的值:(ngSubmit)=onSubmit(password.value)。

以上是关于将 Angular 8 应用程序迁移到 9 的奇怪问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 iframe 将 AngularJS 迁移到 Angular 8

仅 IOS 8 中的核心数据迁移问题,而不是 IOS 9

Angular 2.0.0 Metadata_resolver 奇怪的行为

将 ASP.Net Core Angular 模板从版本 8 更新到 9

在 Angular 9 中迁移到 Jest 会出现“未定义区域”错误

如何将Vmware Esxi下虚拟机数据迁移到另外一个ESXi主机