glide icon indicating copy to clipboard operation
glide copied to clipboard

GlideJS destroy() function causes 'resize' event error.

Open Danielvandervelden opened this issue 6 years ago • 7 comments

Hi,

So I'm having issues with the destroy functionality. I want the carousel to be initialized on mobile phones, and on resize if the window width is bigger than the JSON init property, destroy the carousel. It looks as follows:

initCarousel() {
    if(this.config.init >= this.windowWidth) {
        this.carousel = new Glide(this.el, this.config);
        this.carousel.on('resize', function() {
            this.windowWidth = window.innerWidth;
            if(this.config.init < this.windowWidth && this.carousel != undefined) {
                this.carousel.destroy();
             }
        }.bind(this));
        
        this.carousel.mount();
    }
}

Here you can see I create the carousel if the init property (640px in this case) is larger or equal to the window width. Then I add a resize event listener which checks if the window is bigger than the init property. If so: destroy.

It destroys it just fine. But as soon as the carousel gets destroyed I get the following error in the console:

Uncaught TypeError: Cannot read property 'resize' of undefined
at EventsBinder.off (glide.esm.js?fe9b:1951)
at Object.unbind (glide.esm.js?fe9b:2006)
at eval (glide.esm.js?fe9b:2015)
at eval (glide.esm.js?fe9b:556)
at Array.forEach (<anonymous>)
at EventsBus.emit (glide.esm.js?fe9b:555)
at Glide$$1.destroy (glide.esm.js?fe9b:699)
at VlCarousel.eval (module.gallery.js?e992:30)
at eval (glide.esm.js?fe9b:556)
at Array.forEach (<anonymous>)

Do I need to unbind this resize event somewhere?

Danielvandervelden avatar Jul 17 '19 14:07 Danielvandervelden

@Danielvandervelden can you try ::-

this.carousel._e.on('resize' ......

The Eventbus is attached to this._e on the Glide class hence this syntax

gautamz07 avatar Jul 17 '19 15:07 gautamz07

I experienced the same error, when I tried to mount and destroy slider depending on window's width. Pseudocode:

{
  constructor() {
    this.carousel = new Glide(this.element);
    this.attachListeners();

    this.toggle();
  }

  mount() {
    this.carousel.mount();
    this.destroyed = false;
  }

  unmount() {
    if (this.carousel) {
      this.carousel.destroy();
      this.destroyed = true;
    }
  }

  attachListeners() {
     window.addEventListener('resize', this.resize);
  }

  resize = debounce(() => {
    this.toggle();
  }, 200);

  toggle() {
    if (window.innerWidth > 1024) {
      this.unmount();
    } else if (this.destroyed) {
      this.mount();
    }
  }
}

This uncaught error breaks carousel destroying process, so carousel is randomly destroyed. I'm not sure how to make a workaround. Any help would be grateful.

EDIT

It looks like Event's Binder destroy() is called one extra time, just before calling off(). Probably Resize component is calling destroy() too many times.

mciastek avatar Aug 01 '19 14:08 mciastek

Hi, I'm facing the same error and I don't manage to find any solution Did someone find one or a workaround to this problem? Any help would be appreciated

SylvainFaure avatar Mar 26 '20 14:03 SylvainFaure

if (window.matchMedia('(min-width: 768px)').matches) {
   glide.update({startAt: 0, perView: 1, gap: 0, peek: 0}).disable();
} else {
   glide.enable();
}

it seems that reseting glide settings with update() and then applying disable() helped me.

kozichpolina avatar Nov 18 '20 11:11 kozichpolina

Any plan to fix this? I still have the same issue atm.

terryjiang2020 avatar May 19 '22 13:05 terryjiang2020

Same problem here. Any suggestions for a woraround?

gunvantsharma avatar Feb 25 '23 20:02 gunvantsharma

I tend to run a slider.destroy() when the parent of the slider becomes hidden, and mount the slider again when the container becomes visible. I've experienced the same problem and I've found this issue is caused by the this.listeners getting removed from the GlideJS instance when the slider is destroyed.

Link: https://github.com/glidejs/glide/blob/master/src/core/event/events-binder.js#L56

So far I thought that destroy and mount a slider again would make sense but now I have a doubt. Is the destroy action a way to put the Slider in an unknown state or this has something to do with the instance of the GlideJS class?

Because if it is allowed to run slider.destroy().mount() then, I think the current behavior is a bug. The documentation is also saying 👇

Destroy instance and undo all modifications which have been made to the DOM. It also unbinds added event listeners.

It also unbinds added event listeners.

Which does not mean deleting the instance property listeners, hence to me the solution would be to change the line from

delete this.listeners

to

this.listeners = {}

Nonetheless the document also say

Destroy instance

If this is intend as Class instance, then the behavior could even be correct, even though I think it would be partially correct. I have no knowledge about the entire project but in this case the object instance should become undefined which is probably something the GlideJS cannot do.

I think the slider.mount().destroy() make sense even though the procedure appear to more like a reset or onhold, depends by the use cases, but it should not put the instance of the GlideJS object in an incorrect state which is what is happening.

Looking at the constructor make me think that, the aforementioned solution would be the solution to go with.

Link: https://github.com/glidejs/glide/blob/master/src/core/event/events-binder.js#L7

widoz avatar Aug 18 '23 10:08 widoz