Angular2 Can't bind to DIRECTIVE since it isn't a known property of element

AngularTypescriptDirective

Angular Problem Overview


I generated new @Directive by Angular CLI, it was imported it to my app.module.ts

import { ContenteditableModelDirective } from './directives/contenteditable-model.directive';

import { ChatWindowComponent } from './chat-window/chat-window.component';

@NgModule({
  declarations: [
    AppComponent,
    ContenteditableModelDirective,
    ChatWindowComponent,
    ...
  ],
  imports: [
    ...
  ],
  ...
})

and I try to use in my component (ChatWindowComponent)

<p [appContenteditableModel] >
	Write message
</p>

even if within directive is only Angular CLI generated code:

 import { Directive } from '@angular/core';

 @Directive({
   selector: '[appContenteditableModel]'
 })
 export class ContenteditableModelDirective {

 constructor() { }

 }

I got the error:

zone.js:388 Unhandled Promise rejection: Template parse errors: Can't bind to 'appContenteditableModel' since it isn't a known property of 'p'.

I tried almost every possible changes, following this angular docs everything should work but it does not.

Any help?

Angular Solutions


Solution 1 - Angular

When wrapping a property in brackets [] you're trying to bind to it. So you have to declare it as an @Input.

import { Directive, Input } from '@angular/core';

@Directive({
 selector: '[appContenteditableModel]'
})
export class ContenteditableModelDirective {

  @Input()
  appContenteditableModel: string;

  constructor() { }

}

The important part is, that the member (appContenteditableModel) needs to be named as the property on the DOM node (and, in this case, the directive selector).

Solution 2 - Angular

If you're using a shared module to define the directive make sure it is both declared and exported by the module it's defined in.

// this is the SHARED module, where you're defining directives to use elsewhere
@NgModule({
  imports: [
    CommonModule
  ],
  declarations: [NgIfEmptyDirective, SmartImageDirective],
  exports: [NgIfEmptyDirective, SmartImageDirective]
})

Solution 3 - Angular

I was facing the same issue with a directive declared in a shared module. I'm using this directive to disable a form control.

import { Directive, Input } from '@angular/core';
import { NgControl } from '@angular/forms';

@Directive({
  selector: '[appDisableControl]'
})
export class DisableControlDirective {

  constructor(private ngControl: NgControl) { }

  @Input('disableControl') set disableControl( condition: boolean) {
    const action = condition ? 'disable' : 'enable';
    this.ngControl.control[action]();
  }

}

To work it properly, declare and export the directive in shared module (or any module you are using).

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { DisableControlDirective } from './directives/disable-control/disable-control.directive';

@NgModule({
  declarations: [
    DisableControlDirective
  ],
  imports: [
    CommonModule
  ],
  exports: [DisableControlDirective],
  providers: [],
  bootstrap: []
})
export class SharedModule { }

Now we can use this directive in any module where we are importing SharedModule.

Now to disable a reactive form's control, we can use it like this:

<input type="text" class="form-control" name="userName" formControlName="userName" appDisableControl [disableControl]="disable" />

Mistake I was doing it, I was using only selector (appDisableControl) and passing the disable param to this. but to pass an input param, we have to use it like above.

Solution 4 - Angular

For me the fix was moving the directive references from root app.module.ts (the lines for import, declarations, and/or exports) to the more specific module src/subapp/subapp.module.ts my component belonged to.

Solution 5 - Angular

In sum, because your directive looks like an anchor directive, remove the brackets and it would work.

Actually, I have not found the corresponding sections related to when the brackets should be removed or not, where only one mention I've found is located at the section on dynamic components:

> Apply that to <ng-template> without the square brackets

, which is however not perfectly covered in the Attribute Directives document.

Individually, I agree with you and was thinking that [appContenteditableModel] should be equal to appContenteditableModel and angular template parser might work around whether there is @input() data binding or not automatically, as well. But they seem exactly not processed equally under the hood, even in current Angular Version of 7.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTomas JavurekView Question on Stackoverflow
Solution 1 - Angularnaeramarth7View Answer on Stackoverflow
Solution 2 - AngularSimon_WeaverView Answer on Stackoverflow
Solution 3 - AngularImFarhadView Answer on Stackoverflow
Solution 4 - AngularSushiGuyView Answer on Stackoverflow
Solution 5 - Angular千木郷View Answer on Stackoverflow