Entrada personalizada angular2 rc.5, descriptor de acceso sin valor para control de formulario con nombre no especificado


80

Tengo un componente de entrada personalizado simple como este,

import {Component, Provider, forwardRef} from "@angular/core";
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from "@angular/forms";

const noop = () => {};

const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => CustomInputComponent),
  multi: true
};

@Component({
  selector: 'custom-input',
  template: `

          <input class="form-control" 
                 [(ngModel)]="value" name="somename"
                 (blur)="onTouched()">

  `,
  providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR]
})
export class CustomInputComponent implements ControlValueAccessor{

  //The internal data model
  private _value: any = '';

  //Placeholders for the callbacks
  private _onTouchedCallback: () => void = noop;

  private _onChangeCallback: (_:any) => void = noop;

  //get accessor
  get value(): any { return this._value; };

  //set accessor including call the onchange callback
  set value(v: any) {
    if (v !== this._value) {
      this._value = v;
      this._onChangeCallback(v);
    }
  }

  //Set touched on blur
  onTouched(){
    this._onTouchedCallback();
  }

  //From ControlValueAccessor interface
  writeValue(value: any) {
    this._value = value;
  }

  //From ControlValueAccessor interface
  registerOnChange(fn: any) {
    this._onChangeCallback = fn;
  }

  //From ControlValueAccessor interface
  registerOnTouched(fn: any) {
    this._onTouchedCallback = fn;
  }

}

y tengo un módulo de aplicación como este,

/**
 * Created by amare on 8/15/16.
 */
import { NgModule }                     from '@angular/core';
import { BrowserModule }                from '@angular/platform-browser';
import { ReactiveFormsModule, FormsModule }          from '@angular/forms';
import { AppComponent }                 from './app/app.component';
import {CustomInputComponent} from "./app/shared/custom.input.component";
import {RouterModule} from "@angular/router";
@NgModule({
  imports: [ BrowserModule, ReactiveFormsModule, FormsModule, RouterModule ],
  declarations: [ AppComponent, CustomInputComponent],
  bootstrap: [ AppComponent ]
})
export class AppModule {  
}

y principal

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule }              from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule);

y he usado mi entrada personalizada en uno de mis componentes como se muestra a continuación, pero obtengo 'Sin valor de acceso para control de formulario con atributo de nombre no especificado'.

<custom-input name="firstName" [(ngModel)]="firstName"></custom-input>

y el componente de la aplicación se ve así

import { Component } from '@angular/core';

@Component({
  moduleId: module.id,
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css']
})
export class AppComponent {
  title = 'app works!';

  firstName: string;
}

Tengo el mismo problema con una directiva personalizada que implementa ControlValueAccessor. Funcionaba en RC4 pero obtiene el mismo error que usted para RC5. Esperando que alguien tenga una solución.
— user2444499

38
Intente agregar ngDefaultControla su control, así:<custom-input name="firstName" [(ngModel)]="firstName" ngDefaultControl></custom-input>
— danieleds

@danieleds, muchas gracias, funciona a las mil maravillas, aunque el equipo angular no respondía.
— Amare

1
Tenga cuidado con los paquetes de terceros que pueda estar utilizando: si importa algo que esté utilizando el anterior FORM_DIRECTIVES, ¡romperá su aplicación! Caso en cuestión: github.com/valor-software/ng2-charts/issues/352
— Pete

Para mí, agregando ngDefaultControl antes de [(ngModel)] = "...." funcionó
— theightysapien

Respuestas:


73

agregar ngDefaultControl al componente de entrada personalizado en el host resolvió el problema, gracias @danieleds


8
Esta solución no funcionó para mí. Tengo un nombre aplicado a mi inputy también intenté agregarlo ngDefaultControla la entrada y no funcionó. Todavía me dio el mismo error. En RC5
— prolink007

2
De acuerdo, agregué la propiedad de nombre en html y ngDefaultControl y uso formControl y no funciona.
— Steve K

1
Vea una muy buena explicación sobre cómo ngDefaultControlfunciona: stackoverflow.com/a/46465959/968003 . Esencialmente, agrega default ControlValueAccessor, que actúa como un puente entre la API de formas angulares y un elemento nativo en el DOM.
— Alex Klaus

46

Agregue ngDefaultControl al componente de entrada personalizada. Esto agrega enlace de datos bidireccional, no debería tener que implementar los métodos de acceso al valor a menos que esté haciendo algo único.

<custom-input name="firstName" [(ngModel)]="firstName" ngDefaultControl></custom-input>

12

Agregue ngDefaultControla su entrada. p.ej

<inline-editor type="textarea" [(ngModel)]="editableTextArea" (onSave)="saveEditable($event)" value="valor" ngDefaultControl> </inline-editor> 

Entonces import { FORM_DIRECTIVES } from '@angular/common';

Finalmente directivas: [FORM_DIRECTIVES]

Esto funcionará :) Gracias por los comentarios anteriores


2
Utilice comillas inversas y otros markdowncomandos para que su publicación sea más legible.
— buhtz

4
Estoy usando RC6 y no hay FORM_DIRECTIVESen@angular/common
— Kosmonaft

6
LAS DIRECTIVAS DE FORMULARIO NO SON MÁS CON NG2 FINAL
— Steve K

4

Estaba poniendo [(ngModel)]mi <option>etiqueta en lugar de<select>

Así que sí ... eso causará esto.


Sí ... Tuve el mismo error, colocando el ngModel en un <mat-radio-button>, en lugar del <mat-radio-group>. Grrrrrr ....
— Mike Gledhill

0

Como otro escenario en el que surge esto, había [(ngModel)]especificado un componente personalizado que se reconstruyó y simplificó recientemente, y la nueva versión del componente solo tenía ngModelcomo variable de entrada normal con emisiones.

Esto no fue suficiente : se debe cambiar el nombre de la variable de entrada a algo más ngModel, o el componente debe implementar la ControlValueAccessorinterfaz ( consulte los documentos para obtener más detalles ). Una vez que uno u otro esté completo, ya no obtendrá este error.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.