angle2 rc.5 benutzerdefinierte Eingabe, Kein Wert Accessor für die Formularsteuerung mit nicht angegebenem Namen

79

Ich habe einfache benutzerdefinierte Eingabekomponente wie diese,

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;
  }

}

und ich habe App-Modul wie dieses,

/**
 * 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 {  
}

und main

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

platformBrowserDynamic().bootstrapModule(AppModule);

und ich habe meine benutzerdefinierte Eingabe in einer meiner Komponenten wie unten gezeigt verwendet, erhalte jedoch die Meldung "Kein Wertzugriff für die Formularsteuerung mit nicht angegebenem Namensattribut".

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

und die app.component sieht so aus

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;
}
Amare
quelle
Ich habe das gleiche Problem mit einer benutzerdefinierten Direktive, die ControlValueAccessor implementiert. Es hat in RC4 funktioniert, aber es wird der gleiche Fehler wie bei RC5 angezeigt. Ich hoffe, jemand hat eine Lösung.
user2444499
38
Versuchen Sie ngDefaultControl, Ihre Kontrolle wie <custom-input name="firstName" [(ngModel)]="firstName" ngDefaultControl></custom-input>
folgt zu erweitern
@danieleds vielen Dank, es funktioniert wie ein Zauber, obwohl das eckige Team nicht reagiert hat.
Amare
1
Hüten Sie sich vor Paketen von Drittanbietern, die Sie möglicherweise verwenden. Wenn Sie etwas importieren, das das alte verwendet FORM_DIRECTIVES, wird Ihre App beschädigt! Ein typisches Beispiel
Pete
Für mich hat das Hinzufügen von ngDefaultControl vor [(ngModel)] = "...." funktioniert
themightysapien

Antworten:

73

Durch Hinzufügen von ngDefaultControl zur benutzerdefinierten Eingabekomponente auf dem Host wurde das Problem behoben, danke an @danieleds

Amare
quelle
8
Diese Lösung hat bei mir nicht funktioniert. Ich habe einen Namen auf meine angewendet inputund ich habe auch versucht ngDefaultControl, die Eingabe hinzuzufügen , und es hat nicht funktioniert. Gab mir immer noch den gleichen Fehler. In RC5
prolink007
2
Ich stimme zu, ich habe die Eigenschaft name in html und ngDefaultControl hinzugefügt und ich verwende formControl und es funktioniert nicht.
Steve K
1
Eine sehr gute Erklärung zur Funktionsweise finden Sie ngDefaultControlunter stackoverflow.com/a/46465959/968003 . Im Wesentlichen wird die Standardeinstellung hinzugefügt ControlValueAccessor, die als Brücke zwischen der Angular Forms-API und einem nativen Element im DOM fungiert.
Alex Klaus
46

Fügen Sie der benutzerdefinierten Eingabekomponente ngDefaultControl hinzu. Dies fügt eine bidirektionale Datenbindung hinzu. Sie sollten die Value Accessor-Methoden nur implementieren müssen, wenn Sie etwas Einzigartiges tun.

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

Fügen Sie ngDefaultControlIhrer Eingabe hinzu. z.B

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

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

Endlich Richtlinien: [FORM_DIRECTIVES]

Das wird funktionieren :) Danke für die obigen Kommentare

Saminda Kularathne
quelle
2
Bitte verwenden Sie Backticks und andere markdownBefehle, um Ihren Beitrag besser lesbar zu machen.
Buhtz
4
Ich benutze RC6 und es ist nicht FORM_DIRECTIVESin@angular/common
Kosmonaft
6
FORM RICHTLINIEN SIND NICHT MEHR MIT NG2 FINAL
Steve K
4

Ich [(ngModel)]habe <option>stattdessen mein Etikett angelegt<select>

Also ja ... das wird das verursachen.

Ryan Knell
quelle
Ja ... ich hatte den gleichen Fehler, als ich das ngModel auf einen <mat-radio-button> anstatt auf die <mat-radio-group> legte. Grrrrrr ....
Mike Gledhill
0

Als weiteres Szenario, in dem dies auftritt, hatte ich [(ngModel)]eine benutzerdefinierte Komponente angegeben, die kürzlich neu erstellt und vereinfacht wurde, und die neue Version der Komponente hatte nur ngModeleine normale Eingabevariable mit Emits.

Dies war nicht genug - die Eingabevariable muss in etwas anderes umbenannt werden ngModel, oder die Komponente muss die ControlValueAccessorSchnittstelle implementieren ( Einzelheiten finden Sie in den Dokumenten ). Sobald der eine oder andere abgeschlossen ist, wird dieser Fehler nicht mehr angezeigt.

bsplosion
quelle