angular2 rc.5 niestandardowe wejście, brak elementu dostępu do wartości dla kontrolki formularza z nieokreśloną nazwą

80

Mam taki prosty niestandardowy komponent wejściowy,

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

}

i mam taki moduł aplikacji,

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

i główne

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

platformBrowserDynamic().bootstrapModule(AppModule);

i użyłem moich niestandardowych danych wejściowych w jednym z moich składników, jak pokazano poniżej, ale otrzymuję komunikat „Brak metody dostępu do wartości dla formantu formularza z nieokreślonym atrybutem nazwy”.

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

a składnik app.com wygląda następująco

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
źródło
Mam ten sam problem z niestandardową dyrektywą, która implementuje ControlValueAccessor. To działało w RC4, ale pojawia się ten sam błąd co w RC5. Mając nadzieję, że ktoś znajdzie rozwiązanie.
user2444499
38
Spróbuj dodać ngDefaultControldo swojej kontroli, na przykład:<custom-input name="firstName" [(ngModel)]="firstName" ngDefaultControl></custom-input>
danieleds
@danieleds wielkie dzięki, że działa jak urok, mimo że zespół Angular nie odpowiadał.
Amare
1
Uważaj na pakiety innych firm, których możesz używać - jeśli zaimportujesz coś, co wykorzystuje stare FORM_DIRECTIVES, zepsuje to twoją aplikację! Przykład
Pete
Dla mnie dodanie ngDefaultControl przed [(ngModel)] = "...." działało
themightysapien

Odpowiedzi:

73

dodanie ngDefaultControl do niestandardowego komponentu wejściowego w hoście rozwiązało problem, dzięki @danieleds

Amare
źródło
8
To rozwiązanie nie zadziałało. Mam nazwę zastosowaną do mojego, inputa także próbowałem dodać ngDefaultControldane wejściowe i nie zadziałało. Nadal dał mi ten sam błąd. W RC5
prolink007
2
Zgadzam się, dodałem właściwość name w html i ngDefaultControl i używam formControl i to nie działa.
Steve K
1
Zobacz bardzo dobre wyjaśnienie, jak to ngDefaultControldziała - stackoverflow.com/a/46465959/968003 . Zasadniczo dodaje default ControlValueAccessor, który działa jako pomost pomiędzy API Angular formularzy a natywnym elementem w DOM.
Alex Klaus,
46

Dodaj ngDefaultControl do niestandardowego komponentu wejściowego. Dodaje to dwukierunkowe wiązanie danych, nie powinieneś implementować metod dostępu wartości, chyba że robisz coś unikalnego.

<custom-input name="firstName" [(ngModel)]="firstName" ngDefaultControl></custom-input>
Nacięcie
źródło
12

Dodaj ngDefaultControldo swojego wkładu. na przykład

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

Następnie import { FORM_DIRECTIVES } from '@angular/common';

Wreszcie dyrektywy: [FORM_DIRECTIVES]

To zadziała :) Dzięki za powyższe komentarze

Saminda Kularathne
źródło
2
Użyj lewych apostrofów i innych markdownpoleceń, aby Twój post był bardziej czytelny.
buhtz
4
Używam RC6 i nie ma FORM_DIRECTIVESw@angular/common
Kosmonaft
6
DYREKTYWY FORMULARZE NIE MA WIĘCEJ Z NG2 FINAL
Steve K
4

Chowałem [(ngModel)]w moim <option>tagu zamiast<select>

Więc tak ... to spowoduje to.

Ryan Knell
źródło
Tak… Miałem ten sam błąd, umieszczając ngModel na <mat-radio-button>, a nie na <mat-radio-group>. Grrrrrr ....
Mike Gledhill
0

Jako kolejny scenariusz, w którym to się pojawia, [(ngModel)]określiłem niestandardowy komponent, który został niedawno przebudowany i uproszczony, a nowa wersja komponentu miała po prostu ngModelnormalną zmienną wejściową z emisjami.

To nie wystarczyło - zmienna wejściowa musi zostać przemianowana na coś innego ngModellub komponent musi implementować ControlValueAccessorinterfejs ( szczegóły w dokumentacji ). Po zakończeniu jednego lub drugiego nie będziesz już otrzymywać tego błędu.

bsplosion
źródło