Angular2 — определение/внедрение синглтона

У меня определена директива оповещения, например:

import { Component } from 'angular2/core';
import { CORE_DIRECTIVES } from 'angular2/common';
import { Alert } from 'ng2-bootstrap/ng2-bootstrap';

@Component({
  selector: 'alert_directive',
  templateUrl: './shared/directives/alert/alert.html',
  directives: [Alert, CORE_DIRECTIVES]
})
export class AlertDirective {
  alerts:Array<Object> = [ ];

  closeAlert(i:number) {
    this.alerts.splice(i, 1);
  }

  addAlert(message: string, style: string) {
    this.alerts.push({msg: message, type: style, closable: true});
    console.log(this.alerts);
  }
}

Затем я определяю свой компонент app, в который я включаю эту директиву:

import {AlertDirective} from '../../shared/directives/alert/alert';
...
@Component({
  selector: 'app',
  templateUrl: './app/components/app.html',
  styleUrls: ['./app/components/app.css'],
  providers: [UserService, HTTP_PROVIDERS],
  encapsulation: ViewEncapsulation.None,
  directives: [ROUTER_DIRECTIVES, AlertDirective]
})
...

Все это работает, и директива появляется в DOM, относящейся к моему файлу app.html.

Этот app.html файл содержит некоторый глобальный HTML (навигационная панель, нижний колонтитул, alert_directive). Я хочу, чтобы alert_directive был синглтоном, на который я могу изменить массив alerts, чтобы отображать предупреждающие сообщения из любого представления без необходимости добавлять директиву в каждое представление.

Итак, в другом компоненте sign in:

import {Component, ViewEncapsulation} from 'angular2/core';
import {AlertDirective} from '../../shared/directives/alert/alert';
@Component({
  selector: 'sign_in',
  templateUrl: './sign_in/components/sign_in.html',
  styleUrls: ['./sign_in/components/sign_in.css'],
  encapsulation: ViewEncapsulation.Emulated
})
export class SignInCmp {
  alertDirective: AlertDirective;
  constructor(alertDirective: AlertDirective) {
    this.alertDirective = alertDirective;
  }

  showAlert() {
    this.alertDirective.addAlert('test', 'warning');
  }
}

Проблема здесь в том, что я newing создаю новый экземпляр AlertDirective, и поэтому мой метод addAlert добавляется в массив моего нового экземпляра, а не существующего экземпляра, который определен в моем компоненте app.

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


person JMac    schedule 03.02.2016    source источник
comment
Я думаю, что лучше использовать сервис, а не делать этот компонент синглтоном.   -  person sdfacre    schedule 03.02.2016


Ответы (1)


Создайте общую службу (зарегистрированную только в bootstrap()) и используйте ее для связи между компонентами и вашим AlertDirective, например showb в Как я могу обмениваться данными между компонентами в Angular2? Служба также может содержать EventEmitter, чтобы все участники могли подписаться на переданные сообщения.

@Injectable()
export class AlertService {
  command: EventEmitter = new EventEmitter();
}

@Component({
  selector: 'alert_directive',
  templateUrl: './shared/directives/alert/alert.html',
  directives: [Alert, CORE_DIRECTIVES]
})
export class AlertDirective {
  constructor(private alertService: AlertService) {
    alertService.commands.subscribe((command) => { doSomething();}
  }
  alerts:Array<Object> = [ ];

  closeAlert(i:number) {
    this.alerts.splice(i, 1);
  }

  addAlert(message: string, style: string) {
    this.alerts.push({msg: message, type: style, closable: true});
    console.log(this.alerts);
  }
}

@Component({
  selector: 'sign_in',
  templateUrl: './sign_in/components/sign_in.html',
  styleUrls: ['./sign_in/components/sign_in.css'],
  encapsulation: ViewEncapsulation.Emulated
})
export class SignInCmp {
  alertDirective: AlertDirective;
  constructor(alertService: AlertService) {
    this.alertService = alertService;
  }

  showAlert() {
    this.sharedService.command.next({text: 'test', title: 'warning'});
  }
}

bootstrap(AppComponent, [/* other providers */, AlertService]);
person Günter Zöchbauer    schedule 03.02.2016