Ivan Yurov
Ivan Yurov

Reputation: 1618

Ember.js: removing event handler in `willDestroyElement` doesn't happen in time

So I have jquery event handler attached to window, I'm removing it in willDestroyElement hook, but calling the event right after it in test triggers callback anyway (adding some delay in test fixes stuff, but it doesn't seem right...)

  _detachHandlers: Ember.on('willDestroyElement', function() {
    $(window).off('resize');    
  })

test:

  this.render(hbs`
    {{#if show}}
      {{#my-component timesCalled=(mut timesCalled)}}
        <button class='button'>Click me!</button>
      {{/my-component}}
    {{/if}}
  `);
  assert.ok(this.$('button.button').length, 'renders button');
  run(() => $(window).trigger('resize'));
  assert.equal(this.get('timesCalled'), 1, "callback worked one time");

  run(() => this.set('show', false));
  assert.notOk(this.$('button.button').length, 'component disappears');
  run(() => $(window).trigger('resize'));    
  assert.equal(this.get('timesCalled'), 1, "callback detached and counter doesn't change");

I guess I need to wrap something in run, but what? Tried many approaches that seemed meaningful but nothing worked.

Upvotes: 1

Views: 388

Answers (2)

Ivan Yurov
Ivan Yurov

Reputation: 1618

Turned out that willDestroyElement fires after component's object is getting destroyed (or entering in destroying state), so if my event handler does something with the state of component, the solution might be to check isDestroying and isDestroyed flags as well.

Upvotes: 0

Patsy Issa
Patsy Issa

Reputation: 11303

Don't use .on use the willDestroyElement method directly to detach your listeners:

willDestroyElement() {
  Ember.$('window').off('resize');
  return this._super(...arguments);
}

Upvotes: 1

Related Questions