将 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
Angular 2.0.0 Metadata_resolver 奇怪的行为
将 ASP.Net Core Angular 模板从版本 8 更新到 9