How to make a component universally accessible in

2019-01-18 06:03发布

I basically want to create a custom dialog component that I can utilize from anywhere in my Angular2 app regardless of where the using component is in the application tree. For simplicity lets call this my SayHello Component.

Consider the following application tree:enter image description here

So let's say i want SomeComponent.level3.component to call up the dialog in SayHello.component.

In Angular 1.x I would inject RootScope into a controller and light up a dialog that way. Now, I understand (more or less) that for Angular2 you can bubble events (with event emitters) up the component tree, but it seems tedious to bubble an event all the way from SomeComponent.level3.component up the tree and down to SayHello.component.

So I thought I would create a SayHello Service that I would inject anywhere I wanted to light up my dialog. Here is a sketch of the code I have formulated.

myApp.component.ts

import {SayHelloComponent} from "<<folder>>/sayHello.component";
import {BunchOfComponents} from "<<folder>>/bunchOfComponents";

@Component({
    directives: [SayHelloComponent],
    selector: "my-app",
    templateUrl: `<bunch-of-components>Within this component exists
                      SomeComponent.level3.component </bunch-of-components>
                      <say-hello showdialog="{{showDialog}}" message="{{message}}">
                      </say-hello>`

})
export class myAppComponent {
    showDialog = false;
    message = "";

    constructor(private sayHelloService: SayHelloService) {
        this.showDialog = sayHelloService.showDialog;
        this.message = sayHelloService.message;

    }
}

SayHelloService.ts

import {Injectable} from 'angular2/core';

@Injectable()
export class SayHelloService {
    public showDialog: boolean = false;
    public message: string ="";

    constructor() {

    }

}

SayHello.component.ts

import {Component} from "angular2/core";
import {SayHelloService} from "<<folder>>/SayHelloService";
@Component({
    directives: [],
    selector: "say-hello",
    template: "[do hello component]"
})
export class SayHelloComponent {
    @Input() showdialog: boolean;
    @Input() message: string;

       constructor(private sayHelloService: SayHelloService) {

    }
    //This idea here is to detect change in showDialog
    //If true then do an alert with the message
    ngOnChanges(changes: { [propName: string]: SimpleChange }) {
        var obj = changes["showdialog"];
        if (obj !== null) {
            if (changes["showdialog"].currentValue === true) {
                alert(this.message);
                this.sayHelloService.showDialog = false;
            }

        };
    }

}

SomeComponent.level3.component

import {Component} from "angular2/core";
import {SayHelloService} from "<<folder>>/SayelloService";

@Component({
    directives: [],
    selector: "some-component",
    template: "<button (click)='doHello()'>Do say hello</button>"
})
export class PageContactUsComponent {

    constructor(private sayHelloService: SayHelloService) {

    }


    doHello(): void {
        this.sayHelloService.message = "Hello world";
        this.sayHelloService.showDialog = true;
    }
}

appBoot.ts

import {bootstrap} from "angular2/platform/browser";
import {MyAppComponent} from "<<folder>/MyAppComponent";
import {SayHelloService} from "<<folder>>/SayHelloService";

bootstrap(MyAppComponent, [
    SayHelloService
]);

Needless to say, this doesn't work. I don't get any errors, but the SayHello.component does not detect any change in the value of 'showdialog'...so nothing happens. Any ideas as to how to do properly do this would be much appreciated.

2条回答
手持菜刀,她持情操
2楼-- · 2019-01-18 07:02

As mentioned in a comment above,

  • Put an Observable inside the service (note, not an EventEmitter)
  • Put a showDialog() API/method on the service that other components can call. The showDialog() method should call next() to send an event.
  • Your dialog component can subscribe to the event and unhide/show itself when it receives an event.

To wrap an Observable in a service, see this answer.

查看更多
做个烂人
3楼-- · 2019-01-18 07:07

An alternative to using a service is dynamically creating the component using ViewContainerRef/createComponent described here:

https://www.lucidchart.com/techblog/2016/07/19/building-angular-2-components-on-the-fly-a-dialog-box-example/

查看更多
登录 后发表回答