Angular2 Невозможно привязать к DIRECTIVE, так как это неизвестное свойство элемента

92

Я создал новый @Directive с помощью Angular CLI, он был импортирован в мой 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 Отклонение необработанного обещания: ошибки синтаксического анализа шаблона: невозможно выполнить привязку к appContenteditableModel, поскольку это неизвестное свойство p.

Я пробовал почти все возможные изменения, следуя этим документам angular, все должно работать, но это не так.

Любая помощь?

Томаш Явурек
источник
Результат, который мне нужен, [(appContenteditableModel)]="draftMessage.text"в конце ...
Tomas Javurek
Тогда попробуйте вот так<p [appContenteditableModel]="draftMessage.text"></p>
Sanket
Он работает без скобок, appContenteditableModel="draftMessage.text"а также (appContenteditableMode)l="draftMessage.text"разрешает отклонение обещаний, но, похоже, не передает переменную
Томас Явурек

Ответы:

147

Заключая свойство в квадратные скобки, []вы пытаетесь привязать его к нему. Таким образом, вы должны объявить его как файл @Input.

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

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

  @Input()
  appContenteditableModel: string;

  constructor() { }

}

Важная часть заключается в том, что member ( appContenteditableModel) необходимо назвать свойство в узле DOM (и, в данном случае, селектор директив).

naeramarth7
источник
У меня есть ввод @Input ('appContenteditableModel') model : any;и вывод @Output ('appContenteditableModel') update : EventEmitter<any> = new EventEmitter();в моей директиве. Кажется, что модель работает хорошо, но вызываемый эмиттер this.update.emit(value)не меняет значение в родительском компоненте. Что я делаю не так? [(appContenteditableModel)]="draftMessage.text"
Tomas Javurek
На самом деле я пытаюсь «смоделировать» [(ngModel)] вне элемента <input>
Томас Явурек
@Outputпредназначен только для отправки событий. Если вы хотите, чтобы значение было синхронизировано с родительским, вы можете добавить @HostBindingаннотацию.
naeramarth7
Если я правильно понял, @HostBindingэто поможет синхронизировать значение в элементе html, я прав? Этот элемент мне нужно отредактировать, contenteditable="true"чтобы вводимые данные синхронизировались с переменной в том же компоненте.
Tomas Javurek
35

Если вы используете общий модуль для определения директивы, убедитесь, что он объявлен и экспортируется модулем, в котором он определен.

// this is the SHARED module, where you're defining directives to use elsewhere
@NgModule({
  imports: [
    CommonModule
  ],
  declarations: [NgIfEmptyDirective, SmartImageDirective],
  exports: [NgIfEmptyDirective, SmartImageDirective]
})
Simon_Weaver
источник
а что, если они не в одном модуле?
Охад Садан
@OhadSadan Я не совсем понимаю, что вы имеете в виду. Это пример того, когда у вас их нет в одном модуле, и я просто говорю, что обязательно объявите директивы AND export, если вы создаете их в общем модуле (который затем вы должны затем импортировать в другой модуль).
Simon_Weaver
В вашем «основном» модуле вам нужно только импортировать «модуль директив», и тогда все ваши компоненты смогут их увидеть.
Simon_Weaver
Это мелочь, но ее часто упускают. Спасибо !
Сами
2

Для меня исправление двигалось директива ссылка из корня app.module.ts(линии для import, declarationsи / или 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) и передавал ему параметр отключения. но чтобы передать входной параметр, мы должны использовать его, как указано выше.

ИмФархад
источник