Как сделать директивы и компоненты доступными во всем мире

Я написал пользовательскую директиву, которую я использую в своем приложении Angular 2 для закрытия панелей содержимого (некоторые держатели содержимого в моем шаблоне) во всех различных компонентах моего приложения Angular 2. Поскольку этот код совершенно одинаков для каждого компонента, я подумал, что было бы целесообразно написать директиву, которую я мог бы определить один раз, и использовать во всех компонентах. Вот как выглядит моя директива:

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

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

export class CloseContentPanelDirective {
    private el: HTMLElement;

    constructor(el: ElementRef) {
        this.el = el.nativeElement;
    }

    @HostListener('click') onMouseClick() {
        this.el.style.display = 'none';
    }
}

Теперь я ожидал, что смогу импортировать эту директиву один раз в родительский компонент app.component и что затем смогу использовать эту директиву во всех дочерних компонентах. К сожалению, это не работает, поэтому мне придется импортировать эту директиву в каждый компонент отдельно. Я делаю что-то неправильно? Или это поведение просто невозможно?

Ответы на вопрос(1)

Решение Вопроса

обновление> = RC.5

Вы должны импортировать модуль в любой модуль, который вы хотите использовать, компоненты, директивы или каналы импортируемого модуля. Обойти это невозможно.

Что вы можете сделать, это создать модуль, который экспортирует несколько других модулей (например,BrowserModule что экспортируетCommonModule.

@NgModule({
  declarations: [CoolComponent, CoolDirective, CoolPipe],
  imports: [MySharedModule1, MySharedModule2],
  exports: [MySharedModule1, MySharedModule2, CoolComponent, CoolDirective, CoolPipe],
})
export class AllInOneModule {}

@NgModule({
  imports: [AllInOneModule]
})
class MyModule {}

Таким образом, вы делаете все экспортируемымAllInOneModule доступенMyModule.

Смотрите такжеhttps://angular.io/docs/ts/latest/guide/ngmodule.html

обновление <= RC.5

bootstrap(AppComponent, [provide(PLATFORM_DIRECTIVES, {useValue: [CloseContentPanelDirective], multi: true})]);

Смотрите комментарии ниже - хотя для руководства по стилюproviders в корневом компоненте следует отдавать предпочтениеboostrap() это не работает:

оригинал

На корневой компонент добавить

@Component({
  selector: 'my-app',
  providers: [provide(PLATFORM_DIRECTIVES, {useValue: [CloseContentPanelDirective], multi: true})],
  templat: `...`
})
export component AppComponent {
}

@Component(), @Directive(), @Pipe() уже включают@Injectable(), Нет необходимости добавлять его туда также.

 Günter Zöchbauer27 нояб. 2016 г., 14:35
Я обновил свой ответ
 Günter Zöchbauer09 янв. 2017 г., 16:49
Часть передОбновить все еще правда. Невозможно предоставить директивы или компоненты в глобальном масштабе, все, что вы хотите использовать, необходимо добавить вimports: [] текущего модуля.
 hY8vVpf3tyR57Xib01 июн. 2016 г., 09:31
Директивы и поставщики не работали для меня, загрузчик сделал. Если вы упомянете это в своем ответе, я приму это!
 Günter Zöchbauer01 июн. 2016 г., 08:48
На самом деле, я не пробовал это вproviders: [...] компонента сам пока. Я разместил код таким образом, потому что руководство по стилю препятствует использованиюbootstrap(), Вы можете попробовать добавить его вdirectives: [] вместо.
 Cranio09 янв. 2017 г., 16:48
@ GünterZöchbauer это все еще верно для Angulr v2.4.x?
 IvanSt27 нояб. 2016 г., 14:30
Любая идея, как это можно сделать в последней версии Angular2? Кажется, просто объявление его в главном модуле не помогает, а провайдеры и PLATFORM_DIRECTIVES кажутся ограниченными.
 hY8vVpf3tyR57Xib01 июн. 2016 г., 08:45
Спасибо! Ответ работает, когда я добавляю это в файл начальной загрузки моего приложения, а не когда я добавляю его в корневой компонент. Как я понимаю, добавление его в файл начальной загрузки не является лучшей практикой, у вас есть идея, что это может быть?
 IvanSt27 нояб. 2016 г., 15:30
Вы уверены, что были быстрыми! Спасибо вам большое!
 Günter Zöchbauer01 июн. 2016 г., 09:36
Спасибо за тестирование и ваши отзывы! Я обновил мой ответ. Просто чтобы ты знал. Вы также можете добавитьROUTER_DIRECTIVES лайк[CloseContentPanelDirective, ROUTER_DIRECTIVES] сделать их доступными во всем мире. Я показываю это только для того, чтобы понять, как это работает, возможно, вы не захотите это делать.

Ваш ответ на вопрос