【问题标题】:How to declare a directive globally for all modules?如何为所有模块全局声明指令?
【发布时间】:2017-05-21 04:45:07
【问题描述】:

我正在开发一个遵循 Angular(英雄之旅)官方教程的 Github 存储库。你可以看到所有的代码here

我的问题是,我在应用程序的主模块 (app.module) 中声明了一个指令,如果我在 AppComponent 中使用它,它效果很好(该指令仅突出显示 DOM 中的文本元素)。

但是我在AppModule 中有另一个名为HeroesModule 的模块,在这个模块的一个组件中,这个指令不起作用。

主要代码,这里:

app/app.module.ts

...

import { HighlightDirective } from "./shared/highlight.directive";

@NgModule({
    imports: [
        BrowserModule,
        FormsModule,
        HttpModule,
        InMemoryWebApiModule.forRoot(InMemoryDataService),
        AppRoutingModule,
        CoreModule,
        HeroesModule
    ],
    declarations: [
        AppComponent,
        HeroTopComponent,
        HighlightDirective <-------
    ],
    providers: [
        { provide: APP_CONFIG, useValue: AppConfig }
    ],
    bootstrap: [ AppComponent ]
})

...

app/heroes/heroes.module.ts

@NgModule({
    imports: [
        CommonModule,
        FormsModule,
        HeroRoutingModule
    ],
    declarations: [
        HeroListComponent,
        HeroSearchComponent,
        HeroDetailComponent,
        HeroFormComponent
    ],
    providers: [
        HeroService
    ],
    exports: [
        HeroSearchComponent
    ]
})

app/shared/highlight.directive.ts

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

@Directive({ selector: '[tohHighlight]' })

export class HighlightDirective {
    constructor(el: ElementRef) {
        el.nativeElement.style.backgroundColor = 'yellow';
    }
}

app/app.component.ts

<h1 tohHighlight>{{title}}</h1> <----- HERE WORKS
<toh-nav></toh-nav>
<router-outlet></router-outlet>

app/heroes/hero-list/hero-list.component.ts

<div *ngIf="selectedHero">
    <h2>
        {{selectedHero.name | uppercase}} is my hero
    </h2>
    <p tohHighlight>Test</p> <----- HERE IT DOESN'T
    <button (click)="gotoDetail()">View Details</button>
</div>

如果需要,您可以在 Github 存储库中自行查看、安装和测试它。

【问题讨论】:

  • 1.该指令应该属于一个模块 2。一种选择是您可以为所有指令创建一个单独的模块并将新的模块注入您的主应用程序模块
  • 将其移至另一个模块(功能模块),然后将此模块添加到您要使用它的每个模块的import: []
  • @GünterZöchbauer 你是对的。例外的答案是错误的。您仍然不需要将它导入到您需要导出的每个模块中。只有注入器/服务被提升到根目录(除非懒惰)
  • 我遇到的一个陷阱是,对模块结构的更改可能不会被“热”构建过程吸收。我通常使用 webpack 开发服务器(带有@ngtools/webpack 插件),我正在努力弄清楚为什么我的指令没有被应用。重新启动构建过程后,它立即生效。

标签: angular angular2-directives angular2-modules


【解决方案1】:

如果需要使用指令

@Directive({
  selector: '[appMyCommon]'
})
export class MyCommonDirective{}

您应该在任何地方创建一个新模块。

如果您使用 Angular CLI,您可以生成:

ng g module my-common

模块:

@NgModule({
 declarations: [MyCommonDirective],
 exports:[MyCommonDirective]
})
export class MyCommonModule{}

重要! exports 允许您在模块之外使用指令。

最后,在需要使用指令的每个模块中导入该模块。

例如:

@NgModule({
  imports: [MyCommonModule]
})
export class AppModule{}

示例:Plunker

【讨论】:

  • 所以,在这种情况下,我有另一个我没有提到的模块,称为 CoreModule。如果我在该模块中导出指令,并在 AppModule 中导入 CoreModule,这应该适用于所有组件吗?因为它不... :(
  • 在 AppModule 声明的组件上它会起作用,但是您需要在每个想要使用公共组件的独立模块上导入 MyCommonModule。
  • 谢谢!!最后我解决了这个问题,创建了一个名为 SharedModule 的新模块(声明和导出指令)并将其导入 AppModule 和 HeroesModule。但是,是否有可能只在 AppModule 中导入,并将其继承到 AppModule 导入的所有模块中?
  • @YairTawil ionic 如何导入他的所有组件,而无需在每个模块中声明?在哪里定义为全局?例如: 等?
  • That is simply not true. 如果您有另一个具有组件的模块,并且该组件需要您的另一个模块的某些内容 - 即使您将其导出到根目录 - 它也不会被新模块识别。只有注射器可以
【解决方案2】:

根据@CrazyMac 的评论,一个好方法是创建一个DirectivesModule。在这个模块中,你可以声明和导入你所有的指令,然后你就可以在任何你想要的地方导入这个模块。

app/modules/directives/directives.module.ts

import { NgModule } from '@angular/core';
import { HighlightDirective } from './highlight.directive';

@NgModule({
  imports: [],
  declarations: [HighlightDirective],
  exports: [HighlightDirective]
})
export class DirectivesModule { }

app/modules/directives/highLight.directive.ts

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

@Directive({ selector: '[myHighlight]' })
export class HighlightDirective {
  constructor(el: ElementRef) {
    el.nativeElement.style.backgroundColor = 'yellow';
  }
}

app/modules/otherModule/other-module.module.ts

import { DirectivesModule } from '../directives/directives.module';

@NgModule({
  imports: [
    DirectivesModule
  ],
  declarations: []
})
export class OtherModule { }

【讨论】:

  • 这应该是公认的答案。需要将指令导入到将使用它的每个模块中。您不能全局声明指令。 angular.io/guide/sharing-ngmodules
  • 同意!!我只是面临同样的问题,即使采用公认的答案方法也没有用!我可以通过在我使用指令的模块中加载我的指令模块来做到这一点!
  • 我无法为 Angular9 工作。不知道我错过了什么..
猜你喜欢
  • 2017-03-31
  • 2015-07-25
  • 1970-01-01
  • 2019-01-04
  • 1970-01-01
  • 2017-10-19
  • 1970-01-01
  • 2018-01-28
  • 2012-03-06
相关资源
最近更新 更多