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

Я написал специальную директиву, которую использую в своем приложении 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, а затем использовать эту директиву во всех дочерних компонентах. К сожалению, это не работает, поэтому мне пришлось бы импортировать эту директиву в каждый компонент отдельно. Я делаю что-то неправильно? Или такое поведение просто невозможно?


person hY8vVpf3tyR57Xib    schedule 01.06.2016    source источник


Ответы (1)


update> = 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

update ‹= 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(). Не нужно его туда добавлять.

person Günter Zöchbauer    schedule 01.06.2016
comment
Спасибо! Ответ работает, когда я добавляю это в файл начальной загрузки своего приложения, а не когда я добавляю его в корневой компонент. Насколько я понимаю, добавление его в файл начальной загрузки - не лучшая практика, вы знаете, что это может быть? - person hY8vVpf3tyR57Xib; 01.06.2016
comment
Собственно, сам еще не пробовал в providers: [...] компоненте. Я разместил код таким образом, потому что руководство по стилю не рекомендует использовать bootstrap(). Вместо этого вы можете попробовать добавить его в directives: []. - person Günter Zöchbauer; 01.06.2016
comment
Директивы и поставщики у меня не работали, бутстрап работал. Если вы укажете это в своем ответе, я приму это! - person hY8vVpf3tyR57Xib; 01.06.2016
comment
Спасибо за тестирование и ваш отзыв! Я обновил свой ответ. Просто чтобы ты знал. Вы также можете добавить ROUTER_DIRECTIVES как [CloseContentPanelDirective, ROUTER_DIRECTIVES], чтобы сделать их доступными глобально. Я показываю это только для того, чтобы понять, как это работает, возможно, вам не захочется этого делать. - person Günter Zöchbauer; 01.06.2016
comment
Есть идеи, как это можно сделать в последней версии Angular2? Простое объявление этого в основном модуле, похоже, не помогает, а provide и PLATFORM_DIRECTIVES кажутся обесцененными. - person IvanSt; 27.11.2016
comment
Вы точно были быстрыми! Большое спасибо! - person IvanSt; 27.11.2016
comment
@ GünterZöchbauer, это все еще верно для Angulr v2.4.x? - person Cranio; 09.01.2017
comment
Часть перед обновлением все еще верна. Невозможно предоставить директивы или компоненты глобально, все, что вы хотите использовать, необходимо добавить в imports: [] текущего модуля. - person Günter Zöchbauer; 09.01.2017