【问题标题】:ERROR Error: No value accessor for form control with unspecified name attribute on switchERROR 错误:在开关上没有具有未指定名称属性的表单控件的值访问器
【发布时间】:2018-03-07 09:57:24
【问题描述】:

这是我的 Angular 组件:

@Component( {
    selector: 'input-extra-field',
    template: `
            <div class="form-group" [formGroup]="formGroup" >
                <switch [attr.title]="field.etiquette" 
                    [attr.value]="field.valeur" [(ngModel)]="field.valeur"
                    [formControl]="fieldControl" [attr.id]="name" [attr.disabled]="disabled">
                </switch>
                <error-messages [control]="name"></error-messages>
            </div>
    `
} )

这是我的班级:

export class SwitchExtraField extends ExtraField {
    @Input() field: ExtraFormField;
    @Input() entity: { fields: Object };
    @Input() formGroup: FormGroup;

    constructor( formDir: NgForm ) {
        super( null, null, formDir );
    }

    get disabled(): string {
        if ( this.field && !!this.field.saisissable && !this.field.saisissable )     {
            return 'disabled';
        }
        return null;
    }
}

这是我编译时遇到的错误:

ERROR Error: No value accessor for form control with unspecified name attribute
  at _throwError (forms.es5.js:1918)
  at setUpControl (forms.es5.js:1828)
  at FormControlDirective.webpackJsonp.../../../forms/@angular/forms.es5.js.FormControlDirective.ngOnChanges (forms.es5.js:4617)

当我将元素开关更改为输入时,它可以工作,因为我知道我对其他组件使用相同的结构并且它工​​作正常。

【问题讨论】:

标签: angular form-control


【解决方案1】:

我通过将name="fieldName" ngDefaultControl 属性添加到带有[(ngModel)] 属性的元素来修复此错误。

【讨论】:

  • 一些额外的解释会使这成为一个更好的答案。例如,您在哪里找到 ngDefaultControl 的文档?
  • 我认为name="fieldname" 没有必要,但ngDefaultControl 可以解决问题。
  • 更多解释在这里。 stackoverflow.com/questions/46465891/…
  • 添加“ngDefaultControl”(在带有 *ngFor 指令的属性上)解决了我的类似问题。
  • 对我来说,我通过为表单组中使用的元素(例如 AngularEditorModule)导入模块包来解决此问题,以识别模板中的控件,并且 ngDefaultControl 将能够访问它。我在进行单元测试时发现了它。
【解决方案2】:

我遇到了同样的问题,问题是我的子组件有一个名为 formControl@input

所以我只需要改变:

<my-component [formControl]="formControl"><my-component/>

到:

<my-component [control]="control"><my-component/>

ts:

@Input()
control:FormControl;

【讨论】:

  • 与 Angular 10 一起使用,正如在之前的评论中所说,追踪这个真的很难,但是,之后,“formControl”不应该用作组件是有道理的 @Input由于潜在的命名空间冲突,另一个命名解决方案可能是重命名由 FormControl 实例提供的字段 _formControl。
【解决方案3】:

我在 Angular 7 中编写自定义表单控件组件时也收到此错误。但是,没有一个答案适用于 Angular 7。

在我的情况下,需要将以下内容添加到 @Component 装饰器中:

  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => MyCustomComponent),  // replace name as appropriate
      multi: true
    }
  ]

这是一个“我不知道它为什么有效,但确实有效”的案例。将其归咎于 Angular 的糟糕设计/实施。

【讨论】:

  • 这个 sn-p 告诉 Angular 的依赖注入层,当其他类(即 formControlName 指令)向它请求令牌 NG_VALUE_ACCESSOR 时,应该返回您的类。没有它,Angular 将无法知道您的类是自定义表单控件(有关接口等的所有信息在编译过程中都会被删除)
【解决方案4】:

我也有同样的错误,角度 7

 <button (click)="Addcity(city.name)" [(ngModel)]="city.name"  class="dropdown-item fontstyle"
     *ngFor="let city of Cities; let i = index">
      {{city.name}}
 </button>

我刚刚添加了 ngDefaultControl

   <button (click)="Addcity(city.name)" [(ngModel)]="city.name"  ngDefaultControl class="dropdown-item fontstyle"
 *ngFor="let city of Cities; let i = index">
  {{city.name}}

【讨论】:

    【解决方案5】:

    我在运行 Karma 单元测试用例时遇到了这个错误 在导入中添加 MatSelectModule 可以解决问题

    imports: [
            HttpClientTestingModule,
            FormsModule,
            MatTableModule,
            MatSelectModule,
            NoopAnimationsModule
          ],
    

    【讨论】:

    • 只有当你安装了“Angular Material”,否则你不需要这个。
    • 我想补充一点,这适用于 Angular Material 中的任何“输入”元素。例如,我有一个带有表单控件的 Slide Toggle 元素,它在运行 Karma 测试时给了我“无值访问器”错误。事实证明,我必须将 MatSlideToggleModule 导入添加到我的“spec.ts”类中才能识别输入。
    【解决方案6】:

    我在 Jasmine 的单元测试中收到此错误消息。我向自定义元素添加了 ngDefaultControl 属性(在我的情况下,它是一个有角度的材质滑动切换),这解决了错误。

    <mat-slide-toggle formControlName="extraCheese">
      Extra Cheese
    </mat-slide-toggle>
    

    更改上述元素以包含 ngDefaultControl 属性

    <mat-slide-toggle ngDefaultControl formControlName="extraCheese">
     Extra Cheese
    </mat-slide-toggle>
    

    【讨论】:

      【解决方案7】:

      在我的情况下,我忘记将 providers: [INPUT_VALUE_ACCESSOR] 添加到我的自定义组件中

      我将 INPUT_VALUE_ACCESSOR 创建为:

      export const INPUT_VALUE_ACCESSOR = {
        provide: NG_VALUE_ACCESSOR,
        useExisting: forwardRef(() => TextEditorComponent),
        multi: true,
      };
      

      【讨论】:

        【解决方案8】:

        我遇到了同样的错误 - 我不小心将 [(ngModel)] 绑定到我的 mat-form-field 而不是 input 元素。

        【讨论】:

          【解决方案9】:

          当我将其中一个组件输入命名为“formControl”时,我也收到了此错误。可能它是为其他东西保留的。如果你想在组件之间传递 FormControl 对象,可以这样使用:

          @Input() control: FormControl;
          

          不是这样的:

          @Input() formControl: FormControl;
          

          奇怪 - 但工作:)

          【讨论】:

          • 这是因为 formControl 是 Angular 将表单控件绑定到输入字段的默认指令
          【解决方案10】:

          在我的例子中,我使用了指令,但没有将它导入到我的 module.ts 文件中。导入修复它。

          【讨论】:

          • 谢谢,但我还需要重新启动 ng serve 以刷新导入
          【解决方案11】:

          这有点愚蠢,但我不小心使用[formControl] 而不是[formGroup] 得到了这个错误消息。见这里:

          错误

          @Component({
            selector: 'app-application-purpose',
            template: `
              <div [formControl]="formGroup"> <!-- '[formControl]' IS THE WRONG ATTRIBUTE -->
                <input formControlName="formGroupProperty" />
              </div>
            `
          })
          export class MyComponent implements OnInit {
            formGroup: FormGroup
          
            constructor(
              private formBuilder: FormBuilder
            ) { }
          
            ngOnInit() {
              this.formGroup = this.formBuilder.group({
                formGroupProperty: ''
              })
            }
          }
          

          正确

          @Component({
            selector: 'app-application-purpose',
            template: `
              <div [formGroup]="formGroup"> <!-- '[formGroup]' IS THE RIGHT ATTRIBUTE -->
                <input formControlName="formGroupProperty" />
              </div>
            `
          })
          export class MyComponent implements OnInit {
            formGroup: FormGroup
          
            constructor(
              private formBuilder: FormBuilder
            ) { }
          
            ngOnInit() {
              this.formGroup = this.formBuilder.group({
                formGroupProperty: ''
              })
            }
          }
          

          【讨论】:

            【解决方案12】:

            就我而言,问题是我创建了一个 @Input 变量,其保留名称为 formControl

            【讨论】:

              【解决方案13】:

              就我而言,它发生在我的共享模块中,我必须将以下内容添加到@NgModule:

              ...
                imports: [
                  CommonModule,
                  FormsModule,
                  ReactiveFormsModule,
                  IonicModule
                ],
              ...
              

              【讨论】:

              • 随着 ng-zorro 角度组件的更改,这发生在我身上。他们改变了其组件的导入方式。我刚刚错过了复选框组件。
              【解决方案14】:

              就我而言,我在标签上插入了 [(ngModel)] 而不是输入。 还有一个警告,我尝试在指定行中正确运行上述错误但错误不会消失。如果您在其他地方犯了同样的错误,它仍然会在同一行向您抛出同样的错误

              【讨论】:

              • 这是一个很好的答案。有些组件(select、radio 等)你可以像这样滑倒并将 ngModel 粘贴在错误的位置。错误消息没有多大帮助。
              【解决方案15】:

              如果您尝试将 ngModel 添加到&lt;option&gt; HTML 标签等非输入元素,也会发生此错误。确保只将 ngModel 添加到 &lt;input&gt; 标签。 就我而言,我已将 ngModel 添加到 &lt;ion-select-option&gt; 而不是 &lt;ion-select&gt;

              【讨论】:

                【解决方案16】:

                我在 mat-select 中使用 formControl,如下所示:

                <mat-select [formControl]="control">
                 ...
                </mat-select>
                

                我意识到 MatSelectModule 没有导入到 spec 文件中,这解决了这个问题。

                【讨论】:

                  【解决方案17】:

                  如果这对某人有帮助,我会收到此错误,因为我在选择的选项标签内有 ngModel。

                  错误地(我的),我得到了这个:

                  <select class="form-control">
                      <option *ngFor="let mystate of data.states" value="{{mystate.stateAbbreviation}}" [(ngModel)]="dependent.state">{{mystate.stateName}}</option>
                  </select>
                  

                  而不是这个:

                  <select class="form-control" [(ngModel)]="dependent.state">
                      <option *ngFor="let mystate of data.states" value="{{mystate.stateAbbreviation}}" >{{mystate.stateName}}</option>
                  </select>
                  

                  【讨论】:

                  • 这就是发生在我身上的事情!谢谢。
                  【解决方案18】:

                  我遇到了同样的错误,我在自定义表单组件中有一个名为 control 的输入字段,但意外地在名为 formControl 的输入中传递了控制权。希望没有人面临这个问题。

                  【讨论】:

                    【解决方案19】:

                    就我而言,这就像在我的 app.module.ts 声明中为 DI 注册新组件但在导出中没有一样愚蠢。

                    【讨论】:

                    • 是的,这里类似。我只是忘记导入包含自定义控件的库。我花了一段时间才发现,因为它曾经给出冗长的错误“如果这不是 Angular 组件,那么......”。如果我看到了,我会立即知道它是什么。唉。
                    【解决方案20】:

                    在我的例子中,它是一个不存在的 component.member,例如

                    [formControl]="personId"
                    

                    将它添加到类声明中修复它

                    this.personId = new FormControl(...)
                    

                    【讨论】:

                      【解决方案21】:

                      看起来“formControl”是Angular Forms的保留名称,当我将此名称用作组件的输入时,我的实际控制出现了意外行为。如果你问我,这是一个 Angular 错误。只需将您的输入名称替换为“frmCtrl”之类的其他名称即可。

                      【讨论】:

                        【解决方案22】:

                        我遇到了同样的错误,但在我的情况下,这显然是一个同步问题,在渲染组件 html 时。

                        我遵循了此页面上提出的一些解决方案,但其中任何一个都对我有用,至少不是完全有效。

                        真正解决我的错误的是在元素的父 html 标记内编写以下代码 sn-p 。

                        我正在绑定到变量。

                        代码:

                            *ngIf="variable-name"
                        

                        错误是由项目试图渲染页面引起的,显然在评估变量的那一刻,项目找不到它的值。使用上面的代码 sn-p 你确保在渲染页面之前询问变量是否已经初始化。

                        这是我的 component.ts 代码:

                        import { Component, OnInit } from '@angular/core';
                        import { InvitationService } from 'src/app/service/invitation.service';
                        import { BusinessService } from 'src/app/service/business.service';
                        import { Invitation } from 'src/app/_models/invitation';
                        import { forEach } from '@angular/router/src/utils/collection';
                        
                        @Component({
                          selector: 'app-invitation-details',
                          templateUrl: './invitation-details.component.html',
                          styleUrls: ['./invitation-details.component.scss']
                        })
                        export class InvitationDetailsComponent implements OnInit {
                          invitationsList: any;
                          currentInvitation: any;
                          business: any;
                          invitationId: number;
                          invitation: Invitation;
                        
                          constructor(private InvitationService: InvitationService, private BusinessService: 
                        BusinessService) { 
                        this.invitationId = 1; //prueba temporal con invitacion 1
                        this.getInvitations();
                        this.getInvitationById(this.invitationId);
                          }
                        
                           ngOnInit() {
                        
                          }
                        
                          getInvitations() {
                            this.InvitationService.getAllInvitation().subscribe(result => {
                              this.invitationsList = result;
                              console.log(result);
                            }, error => {
                              console.log(JSON.stringify(error));
                            });
                          }
                        
                          getInvitationById(invitationId:number){
                            this.InvitationService.getInvitationById(invitationId).subscribe(result => {
                              this.currentInvitation = result;
                              console.log(result);
                              //this.business=this.currentInvitation['business'];
                               //console.log(this.currentInvitation['business']); 
                             }, error => {
                             console.log(JSON.stringify(error));
                            });
                          }
                              ...
                        

                        这是我的 html 标记:

                        <div class="container-fluid mt--7">
                          <div class="row">
                            <div class="container col-xl-10 col-lg-8">
                              <div class="card card-stats ">
                                <div class="card-body container-fluid form-check-inline" 
                                 *ngIf="currentInvitation">
                                  <div class="col-4">
                                     ...
                        

                        我希望这会有所帮助。

                        【讨论】:

                        【解决方案23】:

                        您是否尝试将您的[(ngModel)] 移动到div 而不是HTML 中的switch?我的代码中出现了同样的错误,这是因为我将模型绑定到&lt;mat-option&gt; 而不是&lt;mat-select&gt;。虽然我没有使用表单控件。

                        【讨论】:

                          【解决方案24】:

                          在我的例子中,错误是由复制模块中的组件导入触发的。

                          【讨论】:

                            【解决方案25】:

                            #背景

                            • NativeScript 6.0

                            在我的例子中,错误是通过将元素标签从错误更改为触发的。在

                            删除 [(ngModel)]="name" 后错误消失了。

                            【讨论】:

                              【解决方案26】:

                              我在运行单元测试时遇到了这个问题。为了解决这个问题,我将 MatSlideToggleModule 添加到我的 spec.ts 文件中的导入中。

                              【讨论】:

                                【解决方案27】:

                                在我的例子中,我在转换为 Angular 时有一个来自旧 html 的 &lt;TEXTAREA&gt; 标签。不得不改成&lt;textarea&gt;

                                【讨论】:

                                • 我没有投反对票,但这绝不应该是原因。
                                猜你喜欢
                                • 1970-01-01
                                • 1970-01-01
                                • 2018-03-24
                                • 1970-01-01
                                • 2019-02-09
                                • 2019-08-17
                                • 1970-01-01
                                • 1970-01-01
                                • 2018-10-30
                                相关资源
                                最近更新 更多