如何在另一个组件中获取指令/组件实例?

时间:2016-05-10 11:30:10

标签: javascript angular

我有一个AlertComponent,我想在我的AppComponent中用作指令并公开它,以便它可以(作为一种单例)从AppComponent的所有路径/子组件中获得。但我似乎无法找到一种方法来获取AlertComponent对象的实例作为指令,以便调用它的方法并查看对指令所做的更改(即向/从页面添加/删除警报)。 / p>

这是AlertComponent:

import { Component } from 'angular2/core';

import { Alert } from './model';

@Component({
    selector: 'alerts',
    templateUrl: './alert/index.html'
})
export class AlertComponent {
    alerts: Array<Alert>;

    constructor() {}

    add(alert: Alert) {
        this.alerts.push(alert);
    }

    remove(index: number) {
        this.alerts.splice(index, 1);
    }

    clear() {
        this.alerts = [];
    }
}

export { Alert };

和AppComponent:

import { Component, OnInit, provide } from 'angular2/core';
import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from 'angular2/router';
import { HTTP_PROVIDERS, RequestOptions } from 'angular2/http';
import { CookieService } from 'angular2-cookie/core';

import { UserComponent } from '../user/component';
import { AlertComponent, Alert } from '../alert/component';

import { ExtendedRequestOptions } from '../extended/RequestOptions';
import { UtilObservable } from '../util/observable';

@Component({
    selector: 'app',
    template: `
<alerts></alerts>
<router-outlet></router-outlet>
`,
    //styleUrls: [ 'app/style.css' ],
    directives: [
        ROUTER_DIRECTIVES,
        AlertComponent
    ],
    providers: [
        ROUTER_PROVIDERS,
        HTTP_PROVIDERS,
        provide(RequestOptions, { useClass: ExtendedRequestOptions }),
        CookieService,
        UtilObservable,
        AlertComponent
    ]
})
@RouteConfig([{
    path: '/user/:action',
    name: 'User',
    component: UserComponent,
    useAsDefault: true
}
])
export class AppComponent implements OnInit {

    constructor(public _alert: AlertComponent) {}

    ngOnInit() {
        this._alert.add(new Alert('success', 'Success!'));
    }
}

我希望将相同的AlertComponent实例用于AppComponent的所有后代路由/子节点(例如UserComponent),以便向同一指令添加警报。

这可能吗?或者还有另一种更合适的方法吗?

[更新]

所选解决方案回答了标题问题,但我也希望有一个简单的解决方案来在我的组件之间共享警报。以下是如何做到这一点:

AlertComponent:

import { Component } from 'angular2/core';

import { Alert } from './model';

export class Alerts extends Array<Alert> {}

@Component({
    selector: 'alerts',
    templateUrl: './alert/index.html'
})
export class AlertComponent {
    constructor(public alerts: Alerts) {}

    add(alert: Alert) {
        this.alerts.push(alert);
    }

    remove(index: number) {
        this.alerts.splice(index, 1);
    }

    clear() {
        this.alerts.length = 0;
    }
}

export { Alert };

AppComponent:

import { Component, provide } from 'angular2/core';
import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from 'angular2/router';
import { HTTP_PROVIDERS, RequestOptions } from 'angular2/http';

import { AlertComponent, Alerts } from '../alert/component'
import { UserComponent } from '../user/component';

import { ExtendedRequestOptions } from '../helpers/extensions';

@Component({
    selector: 'app',
    template: `<router-outlet></router-outlet>`,
    directives: [
        ROUTER_DIRECTIVES
    ],
    viewProviders: [
        provide(Alerts, { useValue: [] })
    ],
    providers: [
        ROUTER_PROVIDERS,
        HTTP_PROVIDERS,
        provide(RequestOptions, { useClass: ExtendedRequestOptions })
    ]
})
@RouteConfig([{
    path: '/user/:action',
    name: 'User',
    component: UserComponent,
    useAsDefault: true
}
])
export class AppComponent {}

基本上,我提供了每个AlertComponent使用的单一警报数组。

如果你想在指令之外使用它,你可以将provide()移动到提供者(而不是viewProviders),但如果没有,请保持简单并以这种方式限制它。

希望这有助于某人:)

2 个答案:

答案 0 :(得分:2)

您需要使用ViewChild装饰器来引用它:

@Component({
})
export class AppComponent implements OnInit {
  @ViewChild(AlertComponent)
  _alert: AlertComponent;

  ngAfterViewInit() {
    // Use _alert
    this._alert.add(new Alert('success', 'Success!'));
  }
}

@ViewChild在调用ngAfterViewInit挂钩方法之前设置。

答案 1 :(得分:2)

  

将它暴露给所有人,使其可用(作为一种单身人士)   来自AppComponent的路由/子组件。

  

还是有另一种更合适的方法吗?

AlertComponent创建和引导服务,就像这样

<强> AlertService

import {Injectable} from '@angular/core';
import {Subject} from 'rxjs/Subject';
import 'rxjs/add/operator/share';

@Injectable()
export class AlertService {
  private _alerts: Array<Alert> = [];
  public alertsChange: Subject<Array<Alert>> = new Subject();

  public get alerts(): Array<Alert> {
    return this._alerts;
  }

    add(alert: Alert) {
        this._alerts.push(alert);
        this.alertsChange.next(this._alerts);
    }

    remove(index: number) {
        this._alerts.splice(index, 1);
        this.alertsChange.next(this._alerts);
    }

    clear() {
        this._alerts = [];
        this.alertsChange.next(this._alerts);
    }
}

Bootstrap AlertService

import {bootstrap} from '@angular/platform-browser-dynamic';
import {YourApp} from 'path/to/YourApp-Component';
import { AlertService} from 'path/to/alert-service';

bootstrap(YourApp, [AlertService]);

<强> AlertComponent

import { Component } from 'angular2/core';
import { Alert } from './model';
import { AlertService} from 'path/to/alert-service';
@Component({
    selector: 'alerts',
    templateUrl: './alert/index.html'
})
export class AlertComponent {
    alerts: Array<Alert>;

    constructor(alertService: AlertService) {
      alertService.alertsChange.subscribe((moreAlerts: Array<Alert>) => {
         this.alerts = moreAlerts;
      })
    }
}

所有路线/儿童组件

(样品):

import { Component} from '@angular/core';
import { AlertService} from 'path/to/alert-service';
@Component({
   template: `.....`
})
export class SampleComponent {

  constructor(public alerts: AlertService){} 

  ngOnInit(){
    this.alerts.add(new Alert('success', 'Success!'));
  }

  ngOnDestroy(){
    this.alerts.clear();
  }
}

要查看其他类似示例see this question