Reputation: 8436
I'm creating a custom element in Angular 2.0 (<my-select>
), and when I include the ngModel attribute on the component, I'm immediately hit with the following error:
EXCEPTION: No value accessor for '' in [myModel in App@0:195]
Here's a plunker: http://plnkr.co/edit/wlkPWcB92YZASCwCnmcw?p=preview
(Open console to view error)
If you simply comment out the following line from src/app.ts
, the component will render appropriately:
'[ngModel]="myModel"'
I've done the following:
{FORM_DIRECTIVES}
from 'angular2/common'
FORM_DIRECTIVES
in the directives
portion of the @Component
myModel
What am I missing here?
Upvotes: 30
Views: 40337
Reputation: 12603
@DenisKolodin's answer mentions setting the accessor using ngControl.valueAccessor = this;
. However, some articles suggest registering the provider this way instead:
@Component({
selector: '...',
template: '...',
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => MyComponent ),
multi: true,
}
})
export class MyComponent implements ControlValueAccessor{ ...
This is how it's done in Angular's DefaultValueAccessor
source
Upvotes: 2
Reputation: 657248
>=RC.5
@NgModule({
imports: [BrowserModule, FormsModule, ReativeFormsModule],
FormsModule
and/or ReativeFormsModule
depending on whether you use template driven forms, model driven forms or both
See also
Upvotes: 1
Reputation: 71
Try this
import {FORM_DIRECTIVES} from '@angular/forms';
Import any and all forms symbols - NgForm, Validators, etc - from @angular/forms. Importing them from @angular/common will result in a No value accessor found error.
Upvotes: 4
Reputation: 2413
I was not using new Form APIs, and I was still getting this error for NgModel
in my unit test.
Looks like just specifying NgModel
in your component isn't sufficient. e.g.
Before
directives:[NgModel]
After
directives:[FORM_DIRECTIVES]
That fixed my problem. Cheers :)
Upvotes: 2
Reputation: 3008
In my case it was a simple typo error. The component's selector was 'my-component' but in the html I typed <my-compoent>
. Notice last three letters? Compiles just fine and then you have this 'no value accessor' error at runtime.
From my experience you can have some other quite weird errors because of typos here and there. Typescript compiler doesn't care about markup.
Upvotes: 3
Reputation: 15071
I take this error for 2 reasons:
1) Component has to attach itself as a value accessor, like:
@Component({
selector: 'ace-editor',
template: `<div class="ng2-ace-editor"></div>`,
})
export class AceEditor implements OnInit, ControlValueAccessor {
constructor(private element: ElementRef, @Optional() ngControl: NgControl) {
if (ngControl) {
ngControl.valueAccessor = this;
}
}
2) You haven't to mix deprecated and new forms. If you use a new API add to your main.ts
:
import { bootstrap } from '@angular/platform-browser-dynamic';
import { disableDeprecatedForms, provideForms } from '@angular/forms';
import { AppComponent } from './app.component';
bootstrap(AppComponent, [
disableDeprecatedForms(),
provideForms()
])
.catch((err: any) => console.error(err));
Upvotes: 14
Reputation: 3208
I just got this error as well. And it was my stupidity. I will describe it here in case someone else jumps into it.
The format of 2 way binding for passing variables between components (let say I want to pass obj called myObj from Component A to Component B).
So inside the template for Component A I would have something like
<componentB [(myObjectInB)]="myObjectInA"></componentB>
Inside component B, I have to have an object called myObjectInB and the way we declare it must be:
@Input() myObjectInB ...
The @Input() here is what I missed so that's why it threw that error.
Upvotes: 1
Reputation: 14221
I had a similar issue when I was creating a release task in gulp. I tracked it down to an error with the minified versions of the Angular2 code which is what you are using in your plunker. This Angular2 Issue on github is where I found my answer and here is Igor Minar's response to the Issue (Igor is a top contributor to the Angular2 project).
TL;DR; Use the .dev
Angular2 library files until the Angular team fixes this issue.
Upvotes: 2
Reputation:
I got the same problem. I figured that I tried to two-way bind my variable to a <span>
element and then get that value in an attribute:
<span [(ngModel)]="_hidden" [hidden]="_hidden" class="field-validation-error">Username is required.</span>
As you can see, there's no way for the view to modify the _hidden
variable in the model. Fixing the binding to one-way worked:
<span (ngModel)="_hidden" [hidden]="_hidden" class="field-validation-error">Username is required.</span>
Notice the change from [(ngModel)]
to (ngModel)
.
Upvotes: 4
Reputation: 202156
I think you should use something else than ngModel
for the parameter of your my-select
component... Because it's already used by Angular2.
I made a try with model
and it seems better... I don't have the error anymore.
Edit
If you want to handle ngModel at the level of your my-select
component, you could have a look at this link: https://github.com/angular/angular/issues/2543.
If you want to implement an ngModel-compliant component, you could have a look at the following links:
Hope it helps you, Thierry
Upvotes: 13