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;
}
ngDefaultControl
do swojej kontroli, na przykład:<custom-input name="firstName" [(ngModel)]="firstName" ngDefaultControl></custom-input>
FORM_DIRECTIVES
, zepsuje to twoją aplikację! PrzykładOdpowiedzi:
dodanie ngDefaultControl do niestandardowego komponentu wejściowego w hoście rozwiązało problem, dzięki @danieleds
źródło
input
a także próbowałem dodaćngDefaultControl
dane wejściowe i nie zadziałało. Nadal dał mi ten sam błąd. W RC5ngDefaultControl
działa - stackoverflow.com/a/46465959/968003 . Zasadniczo dodaje defaultControlValueAccessor
, który działa jako pomost pomiędzy API Angular formularzy a natywnym elementem w DOM.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.
źródło
Dodaj
ngDefaultControl
do swojego wkładu. na przykładNastępnie
import { FORM_DIRECTIVES } from '@angular/common'
;Wreszcie dyrektywy:
[FORM_DIRECTIVES]
To zadziała :) Dzięki za powyższe komentarze
źródło
markdown
poleceń, aby Twój post był bardziej czytelny.FORM_DIRECTIVES
w@angular/common
Chowałem
[(ngModel)]
w moim<option>
tagu zamiast<select>
Więc tak ... to spowoduje to.
źródło
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 prostungModel
normalną zmienną wejściową z emisjami.To nie wystarczyło - zmienna wejściowa musi zostać przemianowana na coś innego
ngModel
lub komponent musi implementowaćControlValueAccessor
interfejs ( szczegóły w dokumentacji ). Po zakończeniu jednego lub drugiego nie będziesz już otrzymywać tego błędu.źródło