Ember, mixin to detect click outside of view/component

后端 未结 5 976
梦谈多话
梦谈多话 2021-01-06 05:48

I\'m writing a Mixin to handle when user clicks outside of a view/component.

This is the mixin:

App.ClickElsewhereMixin = Ember.Mixin.create({

  onC         


        
相关标签:
5条回答
  • 2021-01-06 05:57

    Greg answer have a mistake, that makes removing the clickHandler event not working. Which means that your clickevent will fire even if you destroy the component.

    Here is proper version

    import Ember from 'ember';
    
    export default Ember.Mixin.create({
        onOutsideClick: Ember.K,
    
      handleOutsideClick: function(event) {
        let $element = this.$();
        let $target = $(event.target);
    
        if (!$target.closest($element).length) {
          this.onOutsideClick();
        }
      },
    
      setupOutsideClickListener: Ember.on('didInsertElement', function() {
    
        let clickHandler = this.get('handleOutsideClick').bind(this);
    
        return Ember.$(document).on('click', clickHandler);
      }),
    
      removeOutsideClickListener: Ember.on('willDestroyElement', function() {
    
        let clickHandler = this.get('handleOutsideClick').bind(this);
    
        return Ember.$(document).off('click', Ember.run.cancel(this, clickHandler));
      })
    });
    
    0 讨论(0)
  • 2021-01-06 05:58

    You have two options:

    1. Use a closure
    2. Use bind

    Closure

    App.ClickElsewhereMixin = Ember.Mixin.create({
    
      onClickElsewhere: Ember.K,
    
      didRender: function() {
        this._super.apply(this, arguments);
        return $(document).on('click', function(this){ return this.get('onClickElsewhere'); }(this));
      },
    
      willDestroyElement: function() {
        this._super.apply(this, arguments);
        $(document).off('click', function(this){ return this.get('onClickElsewhere'); }(this));
      },
    });
    

    Bind

    App.ClickElsewhereMixin = Ember.Mixin.create({
    
      onClickElsewhere: Ember.K,
    
      didRender: function() {
        this._super.apply(this, arguments);
        return $(document).on('click', this.get('onClickElsewhere').bind(this));
      },
    
      willDestroyElement: function() {
        this._super.apply(this, arguments);
        $(document).off('click', this.get('onClickElsewhere').bind(this));
      },
    });
    

    However, not all browsers support bind yet.

    Also, I think you need to use sendAction instead of send in the component (http://guides.emberjs.com/v1.10.0/components/sending-actions-from-components-to-your-application/)

    Edit:

    jQuery.proxy uses call/apply underneath the covers. See this post for a discussion of call/apply vs bind.

    0 讨论(0)
  • 2021-01-06 06:04

    The current answer doesn't check whether the click was actually outside of the element – a click on the component will also trigger the callback.

    Here's an updated version:

    export default Ember.Mixin.create({
      onOutsideClick: Ember.K,
    
      handleOutsideClick: function(event) {
        let $element = this.$();
        let $target = $(event.target);
    
        if (!$target.closest($element).length) {
          this.onOutsideClick();
        }
      },
    
      setupOutsideClickListener: Ember.on('didInsertElement', function() {
        let clickHandler = this.get('handleOutsideClick').bind(this);
    
        return Ember.$(document).on('click', clickHandler);
      }),
    
      removeOutsideClickListener: Ember.on('willDestroyElement', function() {
        let clickHandler = this.get('handleOutsideClick').bind(this);
    
        return Ember.$(document).off('click', clickHandler);
      })
    });
    
    0 讨论(0)
  • 2021-01-06 06:17

    The ember way of doing it is Ember.run.bind. This takes care of binding and the run loop.

    App.ClickElsewhereMixin = Ember.Mixin.create({
    
      onClickElsewhere: Ember.K,
    
      setupListener: Ember.on('didRender', function() {
        this.set('clickHandler', Ember.run.bind(this, this.onClickElsewhere));
        Ember.$(document).click(this.get('clickHandler'));
      }),
    
      removeListener: Ember.on('willDestroyElement', function() {
        Ember.$(document).off('click', this.get('clickHandler'));
      }),
    });
    
    0 讨论(0)
  • 2021-01-06 06:17

    You can use the lib ember-click-outside. Worked for me.

    0 讨论(0)
提交回复
热议问题