不能在 Angular 6 的子模块中使用 app 模块内声明的指令
Posted
技术标签:
【中文标题】不能在 Angular 6 的子模块中使用 app 模块内声明的指令【英文标题】:can't use directive declared inside app module in child modules in Angular 6 【发布时间】:2019-03-09 11:22:25 【问题描述】:我正在使用Angular 6
。
我通过扩展 NbgPopover 声明了一个指令 StickyPopover 并添加了 declaration
的 app.module.ts
import BrowserModule from '@angular/platform-browser';
import NgModule from '@angular/core';
import AppComponent from './app.component';
import AppRoutingModule from './app-routing.module';
import AuthLayoutComponent from './layouts/auth-layout/auth-layout.component';
import AdminLayoutComponent from './layouts/admin-layout/admin-layout.component';
import FormsModule from '@angular/forms';
import RouterModule from '@angular/router';
import BrowserAnimationsModule from '@angular/platform-browser/animations';
import NgbModule from '@ng-bootstrap/ng-bootstrap';
import StickyPopoverDirective from './sticky-popover.directive';
@NgModule(
declarations: [
AppComponent,
AuthLayoutComponent,
AdminLayoutComponent,
StickyPopoverDirective // custom created directive
],
imports: [
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
FormsModule,
HttpClientModule,
RouterModule,
NgbModule.forRoot(),
],
providers: [],
bootstrap: [AppComponent],
)
export class AppModule
并且该指令的位置与app.module.ts文件的位置处于同一级别。
sticky-popover.directive.ts的内容是
import
ElementRef,
Directive, Input, TemplateRef,
EventEmitter,
Renderer2,
Injector,
ComponentFactoryResolver,
ViewContainerRef,
NgZone, OnInit, OnDestroy
from '@angular/core';
import NgbPopover, NgbPopoverConfig from '@ng-bootstrap/ng-bootstrap';
@Directive(
selector: '[appStickyPopover]',
exportAs: 'stickyPopover'
)
export class StickyPopoverDirective extends NgbPopover implements OnInit, OnDestroy
@Input() stickyPopover: TemplateRef<any>;
popoverTitle: string;
placement: 'auto' | 'top' | 'bottom' | 'left' | 'right' | 'top-left' | 'top-right' | 'bottom-left' |
'bottom-right' | 'left-top' | 'left-bottom' | 'right-top' | 'right-bottom' | ('auto' | 'top' | 'bottom' |
'left' | 'right' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'left-top' | 'left-bottom' |
'right-top' | 'right-bottom')[];
triggers: string;
container: string;
shown: EventEmitter<>;
hidden: EventEmitter<>;
ngpPopover: TemplateRef<any>;
canClosePopover: boolean;
toggle(): void
super.toggle();
isOpen(): boolean
return super.isOpen();
constructor(
private _elRef: ElementRef,
private _render: Renderer2,
injector: Injector,
componentFactoryResolver: ComponentFactoryResolver,
private viewContainerRef: ViewContainerRef,
config: NgbPopoverConfig,
ngZone: NgZone
)
super(_elRef, _render, injector, componentFactoryResolver, viewContainerRef, config, ngZone, document);
this.triggers = 'manual';
this.popoverTitle = 'Permissions';
this.container = 'body';
ngOnInit(): void
super.ngOnInit();
this.ngbPopover = this.stickyPopover;
this._render.listen(this._elRef.nativeElement, 'mouseenter', () =>
this.canClosePopover = true;
this.open();
);
this._render.listen(this._elRef.nativeElement, 'mouseleave', (event: Event) =>
setTimeout(() => if (this.canClosePopover) this.close(); , 100);
);
this._render.listen(this._elRef.nativeElement, 'click', () =>
this.close();
);
ngOnDestroy(): void
super.ngOnDestroy();
open()
super.open();
const popover = window.document.querySelector('.popover');
this._render.listen(popover, 'mouseover', () =>
this.canClosePopover = false;
);
this._render.listen(popover, 'mouseout', () =>
this.canClosePopover = true;
setTimeout(() => if (this.canClosePopover) this.close(); , 0);
);
close()
super.close();
我有一个模块 SavedSearches 导入到 AdminModule
内部,该模块在 app.module.ts
当我在 SavedSearches 模块的模板中使用 StickyPopover 指令时,例如
<i class="fa fa-plus-circle" aria-hidden="true" appStickyPopover [popoverTitle]="additional" [autoClose]="true" data-placement="right"></i>
它给出了错误
can't bind to 'popoverTitle' since it isn't a known property of i
当我将指令移入 SavedSearches 模块并将其包含在 saved-searches.module.ts declaration
中时,它可以正常工作,没有任何错误。
但是我不能在另一个模块中使用它并且在其他模块中使用它会给出
StickyPopovoerDirective 是 2 个模块声明的一部分。 将它移到导入这两个模块的上层模块中。
【问题讨论】:
【参考方案1】:该指令仅对AppModule
可见,如果您想将其用于其他模块,您可以创建一个SharedModule
。然后在声明和导出中添加StickyPopoverDirective
。
@NgModule(
declarations: [StickyPopoverDirective],
exports: [StickyPopoverDirective]
)
export class SharedModule
在此之后,您可以将SharedModule
导入另一个模块并在那里使用您的指令。
【讨论】:
如果您使用自定义指令的组件是应用程序模块的一部分,我的意思是只有一个模块,组件和指令都是应用程序模块的一部分?不适用于我,然后为指令创建共享模块,将此共享模块导入应用程序模块...仍然没有运气... 为什么不能从appModule中声明导出?以上是关于不能在 Angular 6 的子模块中使用 app 模块内声明的指令的主要内容,如果未能解决你的问题,请参考以下文章
我可以为 Angular 6 中模块的所有子路由加载一个组件吗?