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

Я спробував майже всі можливі зміни, слідуючи цим кутовим документам, все повинно працювати, але це не так.

Будь-яка допомога?


Результат, який мені потрібен, це [(appContenteditableModel)]="draftMessage.text"в кінці ...
— Томаш Явурек,

Тоді спробуйте так<p [appContenteditableModel]="draftMessage.text"></p>
— Санкет

Він працює без дужок, 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() { }

}

Важливою частиною є те, що член ( appContenteditableModel) потрібно називати властивістю на вузлі DOM (і, в даному випадку, селектором директив).


У моїй директиві є введення, @Input ('appContenteditableModel') model : any;а також вихідні дані @Output ('appContenteditableModel') update : EventEmitter<any> = new EventEmitter();. Здається, модель працює добре, але випромінювач, що викликається, this.update.emit(value)не змінює значення батьківського компонента. Що я роблю неправильно? [(appContenteditableModel)]="draftMessage.text"
— Томаш Явурек,

Насправді я намагаюся "імітувати" [(ngModel)] поза елементом <input>
— Томаш Явурек,

@Outputпризначений лише для випромінювання подій. Якщо ви хочете, щоб значення синхронізувалось із батьківським, можете додати @HostBindingанотацію.
— naeramarth7

Якщо я розумію добре @HostBindingі допоможу синхронізувати значення в елементі html, я не маю рації ? Цей елемент мені потрібно редагувати користувачеві, contenteditable="true"щоб вхідні дані мені потрібно було синхронізувати зі змінною того самого компонента.
— Томаш Явурек

35

Якщо ви використовуєте спільний модуль для визначення директиви, переконайтеся, що вона одночасно оголошена та експортована модулем, у якому вона визначена.

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

а що, якщо вони не в одному модулі?
— Охад Садан,

@OhadSadan Я не впевнений, що саме ти маєш на увазі. Це приклад того, коли у вас їх немає в одному модулі, і я просто кажу, обов’язково оголосіть І експортуйте директиви, якщо ви створюєте їх у спільному модулі (який потім потрібно імпортувати в інший модуль).
— 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) і передавав параметр вимкнення до цього. але щоб передати параметр введення, ми повинні використовувати його, як вище.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.