【问题标题】:Angular2 Can't bind to DIRECTIVE since it isn't a known property of elementAngular2 不能绑定到 DIRECTIVE,因为它不是元素的已知属性
【发布时间】:2017-04-04 00:01:25
【问题描述】:

我通过 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>

即使 inside 指令只是 Angular CLI 生成的代码:

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

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

 constructor() { }

 }

我得到了错误:

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

我尝试了几乎所有可能的更改,遵循angular docs 一切应该可以工作,但它没有。

有什么帮助吗?

【问题讨论】:

  • 我需要的结果最后是[(appContenteditableModel)]="draftMessage.text"...
  • 那就试试这个&lt;p [appContenteditableModel]="draftMessage.text"&gt;&lt;/p&gt;
  • 它在没有括号 appContenteditableModel="draftMessage.text"(appContenteditableMode)l="draftMessage.text" 的情况下工作,解决了承诺拒绝,但它似乎也没有通过变量

标签: angular typescript directive


【解决方案1】:

将属性包装在方括号 [] 中时,您正在尝试绑定到它。所以你必须将它声明为@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&lt;any&gt; = new EventEmitter();。该模型似乎运行良好,但this.update.emit(value) 调用的发射器不会更改父组件中的值。我做错了什么? [(appContenteditableModel)]="draftMessage.text"
  • 实际上我尝试在 元素之外“模拟” [(ngModel)]
  • @Output 仅用于发出事件。如果您想保持值与父值同步,可以考虑添加@HostBinding 注释。
  • 如果我理解得很好 @HostBinding 将有助于保持 html 元素中的值同步,对吗?我需要由用户 contenteditable="true" 编辑此元素,以便我需要与同一组件中的变量保持同步。
  • 啊,谢谢。如果其他人遇到它,我的具体问题是指令选择器(例如selector: 'fooDirective')与@Input() 属性名称(例如@Input() barDirective)不匹配。我重命名了选择器,但也没有考虑属性。
【解决方案2】:

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

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

【讨论】:

  • 如果它们不在同一个模块中怎么办?
  • @OhadSadan 我不确定你的意思。这是当您将它们放在同一个模块中时的示例,我只是说如果您在共享模块中创建它们,请确保声明 AND 导出指令(您然后必须将它们导入到不同的模块中)。
  • 在你的'main'模块中你只需要导入'directives module'然后你的所有组件都可以看到它们。
  • 这是一个微小的细节,但经常被忽略。谢谢!
【解决方案3】:

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

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) 并将禁用参数传递给它。但是要传递输入参数,我们必须像上面一样使用它。

【讨论】:

    【解决方案4】:

    对我来说,修复是将指令引用从根 app.module.tsimportdeclarations 和/或 exports 的行)移动到我的组件所属的更具体的模块 src/subapp/subapp.module.ts

    【讨论】:

    • WTF ???????对此有何解释?它在 2 小时后工作!
    【解决方案5】:

    总而言之,因为你的指令看起来像 anchor directive,去掉括号就可以了。

    实际上,我还没有找到与何时应该删除括号相关的相应部分,我发现只有一个提及位于dynamic components的部分:

    将其应用于&lt;ng-template&gt; 不带方括号

    ,但 Attribute Directives 文档中并未完全涵盖。

    就个人而言,我同意你的看法,我认为[appContenteditableModel] 应该等于appContenteditableModel,并且角度模板解析器也可以自动解决是否存在@input() 数据绑定。但即使在当前的 Angular 版本 7 中,它们似乎也没有得到同等处理。

    【讨论】:

      猜你喜欢
      • 2021-07-11
      • 1970-01-01
      • 2018-10-01
      • 1970-01-01
      • 2017-10-29
      • 2023-04-03
      • 2017-09-01
      • 2017-02-26
      • 2017-02-27
      相关资源
      最近更新 更多