Wygenerowałem nową @Directive przez Angular CLI, zaimportowałem ją do mojego app.module.ts
import { ContenteditableModelDirective } from './directives/contenteditable-model.directive';
import { ChatWindowComponent } from './chat-window/chat-window.component';
@NgModule({
declarations: [
AppComponent,
ContenteditableModelDirective,
ChatWindowComponent,
...
],
imports: [
...
],
...
})
i próbuję użyć w moim komponencie (ChatWindowComponent)
<p [appContenteditableModel] >
Write message
</p>
nawet jeśli wewnątrz dyrektywy jest tylko kod wygenerowany przez Angular CLI:
import { Directive } from '@angular/core';
@Directive({
selector: '[appContenteditableModel]'
})
export class ContenteditableModelDirective {
constructor() { }
}
Wyskoczył mi błąd:
zone.js: 388 Nieobsłużone odrzucenie obietnicy: Błędy analizy szablonu: Nie można powiązać z „appContenteditableModel”, ponieważ nie jest to znana właściwość „p”.
Próbowałem prawie wszystkich możliwych zmian, po tej kątowej dokumentacji wszystko powinno działać, ale tak nie jest.
Jakaś pomoc?
angular
typescript
directive
Tomas Javurek
źródło
źródło
[(appContenteditableModel)]="draftMessage.text"
na końcu ...<p [appContenteditableModel]="draftMessage.text"></p>
appContenteditableModel="draftMessage.text"
a także(appContenteditableMode)l="draftMessage.text"
rozwiązuje problem odrzucenia obietnicy, ale też wydaje się, że nie przekazuje zmiennejOdpowiedzi:
Kiedy zawijasz właściwość w nawiasy
[]
, próbujesz się z nią wiązać. Musisz więc zadeklarować to jako plik@Input
.import { Directive, Input } from '@angular/core'; @Directive({ selector: '[appContenteditableModel]' }) export class ContenteditableModelDirective { @Input() appContenteditableModel: string; constructor() { } }
Ważną częścią jest to, że member (
appContenteditableModel
) musi zostać nazwany jako właściwość w węźle DOM (iw tym przypadku selektor dyrektywy).źródło
@Input ('appContenteditableModel') model : any;
i wyjściowe@Output ('appContenteditableModel') update : EventEmitter<any> = new EventEmitter();
w mojej dyrektywie. Wygląda na to, że model działa dobrze, ale emiter wywołany przezthis.update.emit(value)
nie zmienia wartości w komponencie macierzystym. Co robię źle?[(appContenteditableModel)]="draftMessage.text"
@Output
służy wyłącznie do emitowania wydarzeń. Jeśli chcesz zachować synchronizację wartości z wartością rodzica, możesz rozważyć dodanie@HostBinding
adnotacji.@HostBinding
, pomoże to w utrzymaniu synchronizacji wartości w elemencie HTML, czy mam rację? Ten element musi być edytowany przez użytkownikacontenteditable="true"
, aby dane wejściowe były zsynchronizowane ze zmienną w tym samym komponencie.Jeśli używasz modułu udostępnionego do zdefiniowania dyrektywy, upewnij się, że jest on zadeklarowany i wyeksportowany przez moduł, w którym jest zdefiniowany.
// this is the SHARED module, where you're defining directives to use elsewhere @NgModule({ imports: [ CommonModule ], declarations: [NgIfEmptyDirective, SmartImageDirective], exports: [NgIfEmptyDirective, SmartImageDirective] })
źródło
Dla mnie poprawka poruszał dyrektywy referencje od korzenia
app.module.ts
(dla liniiimport
,declarations
i / lubexports
) do bardziej konkretnego modułusrc/subapp/subapp.module.ts
mój składnik należy.źródło
Podsumowując, ponieważ twoja dyrektywa wygląda jak dyrektywa kotwicy , usuń nawiasy i zadziała.
Właściwie nie znalazłem odpowiednich sekcji związanych z tym, kiedy nawiasy powinny zostać usunięte lub nie, gdzie tylko jedna wzmianka, którą znalazłem, znajduje się w sekcji o komponentach dynamicznych :
, co jednak nie zostało w pełni ujęte w dokumencie dyrektyw dotyczących atrybutów .
Indywidualnie zgadzam się z tobą i myślałem, że
[appContenteditableModel]
powinno to być równe,appContenteditableModel
a kątowy parser szablonów może również obejść, czy istnieje@input()
powiązanie danych, czy też nie automatycznie. Ale wydaje się, że nie są przetwarzane równo pod maską, nawet w obecnej wersji Angular 7.źródło
Miałem ten sam problem z dyrektywą zadeklarowaną w module współdzielonym. Używam tej dyrektywy, aby wyłączyć formant formularza.
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](); } }
Aby to działało poprawnie, zadeklaruj i wyeksportuj dyrektywę w module współdzielonym (lub dowolnym module, którego używasz).
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 { }
Teraz możemy użyć tej dyrektywy w dowolnym module, do którego importujemy SharedModule .
Teraz, aby wyłączyć kontrolkę formularza reaktywnego, możemy jej użyć w następujący sposób:
<input type="text" class="form-control" name="userName" formControlName="userName" appDisableControl [disableControl]="disable" />
Błąd robiłem to, użyłem tylko selektora (appDisableControl) i przekazałem do tego parametr wyłączenia. ale aby przekazać parametr wejściowy, musimy użyć go jak powyżej.
źródło