30
votes

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:

  1. Imported {FORM_DIRECTIVES} from 'angular2/common'
  2. Included FORM_DIRECTIVES in the directives portion of the @Component
  3. Initialized myModel

What am I missing here?

10
What @thierry says. Also adding FORM_DIRECTIVES is not necessary anymore, because they are included by default. Another tip, to make a multiline string in typescript you can use the backticks `. This way you don't need to concatenate the stringPoul Kruijt
@PierreDuc Thanks, see my comment to thierry. Also, I use WebStorm and the syntax highlighting is awful when using the backticks. Need to update the editor, but I do like that shorthand.lux
If you are talking about the background colour. settings -> editor -> colors & fonts -> general -> injected language fragment -> uncheck the background colour.Poul Kruijt
@PierreDuc That's exactly it! Thanks!lux

10 Answers

13
votes

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

14
votes

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));
4
votes

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).

4
votes

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.

3
votes

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.

2
votes

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.

2
votes

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 :)

2
votes

@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

1
votes

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.

1
votes

>=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