Angular2 Tidak dapat mengikat ke DIRECTIVE karena ini bukan properti elemen yang diketahui

92

Saya membuat @Directive baru oleh Angular CLI, itu diimpor ke app.module.ts saya

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

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

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

dan saya mencoba menggunakan di komponen saya (ChatWindowComponent)

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

bahkan jika dalam direktif hanya kode CLI Angular yang dihasilkan:

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

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

 constructor() { }

 }

Saya mendapat kesalahan:

zone.js: 388 Penolakan Janji Tak Tertangani: Kesalahan penguraian template: Tidak dapat mengikat ke 'appContenteditableModel' karena ini bukan properti yang dikenal dari 'p'.

Saya mencoba hampir setiap perubahan yang mungkin, mengikuti dokumen sudut ini semuanya harus berfungsi tetapi tidak.

Ada bantuan?

Tomas Javurek
sumber
Hasil yang saya butuhkan ada [(appContenteditableModel)]="draftMessage.text"di akhir ...
Tomas Javurek
Kemudian coba seperti ini<p [appContenteditableModel]="draftMessage.text"></p>
Sanket
Ini bekerja tanpa tanda kurung appContenteditableModel="draftMessage.text"dan juga (appContenteditableMode)l="draftMessage.text"menyelesaikan penolakan janji tetapi juga tampaknya tidak lulus variabel
Tomas Javurek

Jawaban:

147

Saat membungkus properti dalam tanda kurung, []Anda mencoba mengikatnya. Jadi, Anda harus mendeklarasikannya sebagai file @Input.

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

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

  @Input()
  appContenteditableModel: string;

  constructor() { }

}

Bagian yang penting adalah, bahwa anggota ( appContenteditableModel) perlu dinamai sebagai properti pada simpul DOM (dan, dalam hal ini, pemilih direktif).

naeramarth7
sumber
Saya memiliki masukan @Input ('appContenteditableModel') model : any;dan juga keluaran @Output ('appContenteditableModel') update : EventEmitter<any> = new EventEmitter();dalam direktif saya. Tampaknya model berfungsi dengan baik tetapi emitor yang dipanggil oleh this.update.emit(value)tidak mengubah nilai dalam komponen induk. Apa yang saya lakukan salah? [(appContenteditableModel)]="draftMessage.text"
Tomas Javurek
Sebenarnya saya mencoba untuk "mensimulasikan" [(ngModel)] di luar elemen <input>
Tomas Javurek
@Outputhanya untuk acara yang disiarkan. Jika Anda ingin menjaga agar nilai tetap sinkron dengan nilai induknya, Anda dapat mempertimbangkan untuk menambahkan @HostBindinganotasi.
naeramarth7
Jika saya memahami dengan baik @HostBindingakan membantu untuk menjaga nilai tetap sinkron dalam elemen html, benar kan? Elemen ini saya perlu diedit oleh pengguna contenteditable="true"sehingga input saya perlu tetap sinkron dengan variabel di komponen yang sama.
Tomas Javurek
35

Jika Anda menggunakan modul bersama untuk menentukan direktif, pastikan itu dideklarasikan dan diekspor oleh modul yang ditentukan di dalamnya.

// this is the SHARED module, where you're defining directives to use elsewhere
@NgModule({
  imports: [
    CommonModule
  ],
  declarations: [NgIfEmptyDirective, SmartImageDirective],
  exports: [NgIfEmptyDirective, SmartImageDirective]
})
Simon_Weaver
sumber
dan bagaimana jika mereka tidak berada dalam modul yang sama?
Ohad Sadan
@OhadSadan Saya tidak yakin apa yang Anda maksud. Ini adalah contoh ketika Anda tidak memilikinya dalam modul yang sama, dan saya hanya mengatakan pastikan untuk mendeklarasikan DAN mengekspor direktif jika Anda membuatnya dalam modul bersama (yang kemudian Anda harus mengimpornya ke modul yang berbeda).
Simon_Weaver
Dalam modul 'utama' Anda, Anda hanya perlu mengimpor 'modul direktif' dan kemudian semua komponen Anda dapat melihatnya.
Simon_Weaver
Ini adalah detail kecil tetapi sering terlewat. Terima kasih !
Sami
2

Bagi saya memperbaiki itu bergerak referensi direktif dari akar app.module.ts(garis untuk import, declarationsdan / atau exports) ke modul yang lebih spesifik src/subapp/subapp.module.tskomponen saya milik.

SushiGuy
sumber
1

Singkatnya, karena arahan Anda terlihat seperti arahan jangkar , hapus tanda kurung dan itu akan berhasil.

Sebenarnya, saya belum menemukan bagian yang sesuai terkait kapan tanda kurung harus dilepas atau tidak, di mana hanya satu penyebutan yang saya temukan terletak di bagian komponen dinamis :

Terapkan itu ke <ng-template> tanpa tanda kurung siku

, yang bagaimanapun tidak tercakup secara sempurna dalam Atribut Directive dokumen .

Secara individu, saya setuju dengan Anda dan berpikir itu [appContenteditableModel]harus sama dengan appContenteditableModeldan parser template sudut mungkin bekerja di sekitar apakah ada @input()data yang mengikat atau tidak secara otomatis, juga. Tapi mereka tampaknya benar-benar tidak diproses dengan sama di bawah tenda, bahkan dalam Versi Angular 7 saat ini.

千 木 郷
sumber
1

Saya menghadapi masalah yang sama dengan arahan yang dideklarasikan dalam modul bersama. Saya menggunakan arahan ini untuk menonaktifkan kontrol formulir.

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

}

Untuk bekerja dengan benar, deklarasikan dan ekspor direktif dalam modul bersama (atau modul apa pun yang Anda gunakan).

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

Sekarang kita dapat menggunakan arahan ini di modul mana pun tempat kita mengimpor SharedModule .

Sekarang untuk menonaktifkan kontrol formulir reaktif, kita dapat menggunakannya seperti ini:

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

Kesalahan saya melakukannya, saya hanya menggunakan selector (appDisableControl) dan meneruskan parameter disable ke ini. tetapi untuk mengirimkan parameter masukan, kita harus menggunakannya seperti di atas.

ImFarhad
sumber