2016-05-10 3 views
1

Ich habe eine AlertComponent, die ich gerne als eine Direktive in meiner AppComponent verwenden würde und sie offen legen, damit sie für alle routes/children-Komponenten von AppComponent verfügbar ist (als eine Art Singleton). Aber ich kann anscheinend keine Möglichkeit finden, die Instanz des AlertComponent-Objekts als eine Direktive zu verwenden, um ihre Methoden aufzurufen und die an der Direktive vorgenommenen Änderungen zu sehen (z. B. Hinzufügen/Entfernen von Warnungen zu/von der Seite). HierWie kann ich eine Direktive/Komponenteninstanz in einer anderen Komponente erhalten?

ist 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 }; 

Und 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!')); 
    } 
} 

Ich mag würde die gleiche Instanz von AlertComponent Verfügung, um alle Nachkommen Routen/Kinder AppComponent (zB UserComponent) haben, um Warnungen zu derselben Richtlinie hinzuzufügen.

Ist das möglich? Oder gibt es einen anderen, angemesseneren Weg, dies zu tun?

[Update]

Die gewählte Lösung beantwortet die Titelfrage, aber ich wollte auch eine einfache Lösung haben Warnungen unter meinen Komponenten zu teilen. Hier ist, wie das tun:

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 {} 

Grundsätzlich bin ich ein Singleton Reihe von Warnungen bereitstellt, die von jedem AlertComponent verwendet wird.

Sie können die provide() -Anbieter (anstelle von viewProviders) verschieben, wenn Sie sie außerhalb von Anweisungen verwenden möchten. Wenn nicht, halten Sie sie einfach und beschränken Sie sie auf diese Weise.

hoffte, das hilft jemand :)

Antwort

2

Sie benötigen ViewChild Dekorateur verwenden, um es zu verweisen:

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

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

@ViewChild gesetzt wird, bevor die ngAfterViewInit Hook-Methode aufgerufen wird.

+0

Danke für die Antwort! Gibt es eine Möglichkeit, dass ich dieselben ViewChild/Directive-Daten zwischen zwei oder mehr Komponenten teilen kann? – Kesarion

+0

Ich glaube nicht. In diesem Fall müssen Sie einen gemeinsam genutzten Dienst mit Obserables nutzen. Auf diese Weise können Sie sich benachrichtigen lassen und benachrichtigt werden. Siehe diesen Link für weitere Details: https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service –

2

es freizulegen, so dass es (als eine Art von Singleton) verfügbar ist, zu allen Routen/Kinder Komponenten aus AppComponent.

Oder gibt es eine andere, richtige Weg, dies zu tun?


erstellen und einen Service für AlertComponent Bootstrap, wie dieser

Alert

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 Alert

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; 
     }) 
    } 
} 

Alle Routen/Kinder Komponenten

(Probe):

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(); 
    } 
} 

Für weitere Beispiele gleichermaßen see this question

+0

Das wird definitiv funktionieren. Vielen Dank! Thierry Templier hat aber zuerst die Titelfrage genagelt, also werde ich fair sein und ihm diesen geben. Ich denke, neue Leute wie ich sollten seine Antwort zuerst sehen, bevor sie etwas komplizierteres umsetzen; zum Beispiel habe ich mich für Thierrys einfacheres Beispiel entschieden. Definitiv auch einen Daumen hoch zu dir. Danke noch einmal! – Kesarion

+1

Gern geschehen .... du hast das Richtige getan .... Ich weiß nicht, dass es heikel ist, bescheiden zu handeln, aber das ist sehr nett von dir, um zu klären und Feedback zu geben ... Prost –

Verwandte Themen