【问题标题】:strange problem migrating angular 8 app to 9将 Angular 8 应用程序迁移到 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"

标签: angular


【解决方案1】:

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

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

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

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

编辑:

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

【讨论】:

  • 我在运行 ng serve 时遇到了同样的问题。清理一切并重新安装所有pacakges,但我有同样的问题。在所有模板中,$event 只是在调用组件方法时用作参数。我想问题出在第三方组件中,但我不明白是哪一个
  • 这个问题的解决方案有帮助吗:stackoverflow.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)。
                      猜你喜欢
                      • 2022-11-20
                      • 2020-05-29
                      • 2022-11-28
                      • 1970-01-01
                      • 1970-01-01
                      • 2017-09-19
                      • 1970-01-01
                      • 2020-01-13
                      • 1970-01-01
                      相关资源
                      最近更新 更多