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.