问题
I have a generic pop-up component in my Angular 4 application and in order to correctly handle popup display I need to listen for global click events on the document.
There could be many pop-up components at the same time in the application and I need to close them when user clicks somewhere outside of the those components. I shouldn't bind to document:click event from the component itself for obvious reasons (there should be only one listener), so I've decided to create a centralized service, which would listen for global DOM events on the document and to command the pop-up components.
When pop-up component is initialized, it registers itself with the service and when it's destroyed it deregisters itself. So, the service always has a list of all pop-up components in the application. So far it works great.
However, I've tried to inject the Renderer2 to my centralized service in order to listen for DOM events via it's listen() method, but it looks like it's only available for component injection, not for service injection.
Also, the @HostListener('document:click') decorator is not working in services.
Is my architecture correct? Is it a bad idea for service to listen for DOM events?
The other possible solution would be to create another component instead of the service, but I don't like this approach, because it will require it's manual addition to the application somewhere in contrast with service which is automatically created.
What would be the best way to implement my usage scenario?
回答1:
You should use Observable.fromEvent
sample plunker: https://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5
Create a service similar to this one:
@Injectable()
export class DocService {
obs: Observable;
constructor(){
this.obs = Observable.fromEvent(document, 'click');
}
onClick(): Observable{
return this.obs;
}
}
then subscribe to the observable in your component:
// here I just log the event, in your case, you close the popoup
this.docService.onClick().subscribe(console.log, console.log);
you'll probably need to make sure the click is not hapening on your popup. You can handle this is your subscribe method.
来源:https://stackoverflow.com/questions/44466404/using-service-to-listen-for-dom-events-in-angular