简体   繁体   English

Angular 2 - 绑定和解除绑定HostListener事件

[英]Angular 2 - Binding and Unbinding HostListener Events

I am attempting to bind and unbind a HostListener click event based on a component's input variable. 我试图基于组件的输入变量绑定和解除绑定HostListener单击事件。

The component is a popup which has a single input called show . 该组件是一个弹出窗口,其中包含一个名为show输入。 This input holds the active/inactive state of the popup. 此输入保持弹出窗口的活动/非活动状态。 I would like to fire a click event on the entire document but only when the input show is set to true. 我想在整个文档上触发click事件,但仅当输入show设置为true时才会触发。

Is there a way to bind and unbind the hostlistener event inside the ngOnChanges function I have? 有没有办法在我有的ngOnChanges函数中绑定和取消绑定hostlistener事件?

The current code I have: 我目前的代码:

import {Component, OnInit, Input, ViewEncapsulation, HostListener} from '@angular/core';

@Component({
    selector: 'custom-popup',
    templateUrl: './popup.component.html',
    styleUrls: ['./popup.component.scss'],
    encapsulation: ViewEncapsulation.None
})
export class PopupComponent implements OnInit {

    @Input() show: boolean = false;

    constructor() {
    }

    ngOnInit() {
    }


    @HostListener('document:click', ['$event.target'])
    clickHandler(targetElement) {
        // Custom code to handle click event
    }

    ngOnChanges(show: boolean) {
        if (this.show) {
            // Bind Click Event
        }
        else {
            // Unbind Click Event
        }
    }
}

Any assistance and insight would be greatly appreciated. 任何帮助和见解将不胜感激。

To ensure that only 1 host listener is set up when a popup is shown, introduce a new child component PopupBody that has the host listener on it, and an @Output() to pass the event back up to the Popup component. 要确保在显示弹出窗口时仅设置1个主机侦听器,请引入一个新的子组件PopupBody ,其上包含主机侦听器,以及@Output()将事件传递回Popup组件。

Then, in your template, make the PopupBody component conditional using *ngIf="show" and it should then only bind the host listener when the popup is shown, and unbind it when the popup gets hidden. 然后,在您的模板中,使用*ngIf="show"使PopupBody组件成为条件,然后它应该仅在弹出窗口显示时绑定主机侦听器,并在弹出窗口被隐藏时取消绑定。

In the end I implemented a solution using a service. 最后,我使用服务实现了一个解决方案。 The service handles the click events on the document and uses an observable to enable components to subscribe to the event. 该服务处理文档上的单击事件,并使用observable使组件能够订阅该事件。

The popup component subscribes to the stateService click observable when it is opened and unsubscribes when it is closed. 弹出组件在打开时订阅stateService click observable,在关闭时取消订阅。

Popup Component: 弹出组件:

import {Component, OnInit, Input, ViewEncapsulation, HostListener} from '@angular/core';
import {StateService} from "../services/state.service";
import {Subscription} from "rxjs";  

@Component({
    selector: 'custom-popup',
    templateUrl: './popup.component.html',
    styleUrls: ['./popup.component.scss'],
    encapsulation: ViewEncapsulation.None
})
export class PopupComponent implements OnInit {

    @Input() show: boolean = false;

    constructor(private stateService: StateService) {
    }

    ngOnInit() {
    }

    ngOnChanges(show: boolean) {

        if (this.show) {

            // Timeout to ensure subscription after initial click
            setTimeout(() => {

                // Subscribe to the document click service when the input opens
                if (!this.clickSubscription || this.clickSubscription.closed) {
                    this.clickSubscription = this.stateService.documentClick$.subscribe(targetElement => {
                        // Logic for closing the popup
                    });
                }
            });
        }
        else {

            // Remove the subscription when the input closes
            if (this.clickSubscription && !this.clickSubscription.closed) {
                this.clickSubscription.unsubscribe();
            }
        }
    }
}

@GregL Thank you for your suggestions @GregL感谢您的建议

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM