Angular2无法绑定到DIRECTIVE,因为它不是element的已知属性


91

我通过Angular CLI生成了新的@Directive,将其导入到我的app.module.ts中

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

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

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

我尝试在我的组件(ChatWindowComponent)中使用

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

即使在指令内,只有Angular CLI生成的代码也是如此:

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

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

 constructor() { }

 }

我得到了错误:

zone.js:388未处理的承诺拒绝:模板解析错误:由于它不是'p'的已知属性,因此无法绑定到'appContenteditableModel'。

我尝试了几乎所有可能的更改,按照这个有角度的文档,一切都应该起作用,但事实并非如此。

有什么帮助吗?


我需要的结果是[(appContenteditableModel)]="draftMessage.text"在最后...
Tomas Javurek

然后尝试这样<p [appContenteditableModel]="draftMessage.text"></p>
Sanket

它可以不使用方括号appContenteditableModel="draftMessage.text",也可以(appContenteditableMode)l="draftMessage.text"解决promise拒绝问题,但它似乎也不会传递变量
Tomas Javurek,2016年

Answers:


146

将属性包装在方括号中时,[]您尝试将其绑定。因此,您必须将其声明为@Input

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

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

  @Input()
  appContenteditableModel: string;

  constructor() { }

}

重要的部分是,成员(appContenteditableModel)必须被命名为DOM节点(在这种情况下为指令选择器)上的属性。


我在指令中@Input ('appContenteditableModel') model : any;也有输入和输出 @Output ('appContenteditableModel') update : EventEmitter<any> = new EventEmitter();。该模型似乎运行良好,但是由调用的发射器this.update.emit(value)不会更改父组件中的值。我做错了什么?[(appContenteditableModel)]="draftMessage.text"
Tomas Javurek '16

实际上,我尝试在<input>元素之外“模拟” [(ngModel)]
Tomas Javurek,2016年

@Output仅用于发出事件。如果要使该值与父级保持同步,则可以考虑添加@HostBinding注释。
naeramarth7 '16

如果我理解得很好,@HostBinding将有助于使html元素中的值保持同步,对吗?我需要用户contenteditable="true"对此元素进行编辑,以便我需要与同一个组件中的变量保持同步的输入。
Tomas Javurek '16

35

如果您使用共享模块来定义指令,请确保指令由定义在其中的模块声明和导出。

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

如果它们不在同一模块中怎么办?
Ohad Sadan

@OhadSadan我不确定您的意思是什么。这是一个示例,说明当您不在同一个模块中时,如果要在共享模块中创建它们,请确保声明AND导出指令(然后必须将其导入到不同的模块)。
Simon_Weaver

在“主”模块中,您只需导入“指令模块”,然后所有组件都可以看到它们。
Simon_Weaver

这是一分钟的细节,但经常会遗漏。谢谢 !
萨米

2

对于我修复正从根指令引用app.module.ts(线对importdeclarations和/或exports),以更具体的模块src/subapp/subapp.module.ts我的组件属于。


1

总而言之,由于您的指令看起来像锚指令,因此删除括号即可。

实际上,我还没有找到与何时应该删除括号有关的相应部分,我在动态组件部分仅找到一处提及:

将其应用于<ng-template> 不带方括号的

,但是在“属性指令”文档中并未完全涵盖。

我个人同意您的想法,并认为[appContenteditableModel]应该等于appContenteditableModel并且角度模板解析器也可能会@input()自动解决是否存在数据绑定问题。但是,即使在当前的Angular版本7中,它们似乎也无法在后台进行同样的处理。


1

我在共享模块中声明的指令也面临着同样的问题。我正在使用此指令禁用表单控件。

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]();
  }

}

要使其正常工作,请在共享模块(或您使用的任何模块)中声明并导出指令。

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

现在,我们可以在导入SharedModule的任何模块中使用此指令。

现在要禁用反应形式的控件,我们可以像这样使用它:

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

我这样做是错误的,我只使用选择器(appDisableControl)并将禁用参数传递给它。但是要传递输入参数,我们必须像上面一样使用它。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.