marcelo2605
marcelo2605

Reputation: 2794

swiper.destroy() is not working when have multiples sliders on a page

I have a bunch os swiper instances in the same page and need to destroy/init them based on screen width:

const mobile = window.matchMedia('(max-width: 575.98px)');

function instantiateGridSlider() {
const sliders = [];
$('.thumbnails-grid').each(function(index, element){
    const instance = $(this).data('instance');
    sliders[index] = new Swiper(element, {
    speed: 500,
    spaceBetween: 30,
    slidesPerView: 1,
    loop: true,
    init: false,
    pagination: {
        el: '.swiper-pagination-' + instance,
        type: 'bullets',
        clickable: true,
    },
    });
});

return sliders;
}

function initGridSlider() {
if ($('.thumbnails-grid').length == 0) {
    return;
}

const gridSliders = instantiateGridSlider();
for (let i = 0; i < gridSliders.length; i++) {
    if (mobile.matches) {
    gridSliders[i].init(gridSliders[i].el);
    } else {
    gridSliders[i].destroy(true, true);
    }
}
}

window.addEventListener('resize', function() {
initGridSlider();
});

initGridSlider();

But I'm getting this error when resize the windows to destroy the sliders:

Uncaught TypeError: Cannot read properties of undefined (reading 'children') at Swiper.loopDestroy (loopDestroy.js:6:1) at Swiper.destroy (core-class.js:545:1) at initGridSlider (slider.js:84:1) at slider.js:90:1

Upvotes: 0

Views: 6663

Answers (1)

Ezra Siton
Ezra Siton

Reputation: 7741

In your case - destroy could run more than one time (On resize) - so set deleteInstance to false (true by deafult).

swiper.destroy(deleteInstance, cleanStyles)

**otherwise on the second resize event you get:

Uncaught TypeError: Cannot read properties of null (reading 'destroy') 

Next check in your cases - if for example you did not init the slider and click "destroy" nothing should happen.

Last performance issues - Resize event could run even 100 times (And your code reinstall swiper 100 times X number of sliders). Keep this in mind. It is maybe better to only check the state on load: Do something if screen width is less than 960 px

code snippet

You didn't give full code example. Here is "hello world" example (click destroy/init).

let swiper_setting = {
  spaceBetween: 100,
  pagination: {
    el: '.swiper-pagination',
  }
}

var slider_nodes = document.querySelectorAll('.thumbnails-grid');
let sliders = [];

function loadSwiper(swiper_setting){
  [].forEach.call(slider_nodes, function(slider_node) {
    // do whatever
    let swiper = new Swiper(slider_node, swiper_setting);
    sliders.push(swiper);
  });
  return sliders;
}

loadSwiper(swiper_setting);

$( "#destroy" ).click(function() {
  $(".swiper.thumbnails-grid").each(function(i){
    this.swiper.destroy(false);
  });
});

$( "#init" ).click(function() {
  loadSwiper(swiper_setting);
});

addEventListener('resize', (event) => {
  console.log("resize");
});
html,
body {
  background: #403F6B;
}

.swiper {
  width: 100%;
  height: 100%;
  position: relative;
}

.swiper-slide {
  text-align: center;
  font-size: 18px;
  background: #fff;
  height: 200px!important;
  /* Center slide text vertically */
  display: flex;
  margin-bottom: 40px!important;
  justify-content: center;
  align-items: center;
  margin-bottom: 20px;
}
<link href="https://unpkg.com/swiper@8/swiper-bundle.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://unpkg.com/swiper@8/swiper-bundle.min.js"></script>

<button id="destroy">Destroy All</button>
<button id="init">Init All</button>

<!-- Slider main container --> 
<div class="swiper thumbnails-grid" slider_one>
  <!-- Additional required wrapper -->
  <div class="swiper-wrapper">
    <!-- Slides -->
    <div class="swiper-slide"><a>Slide 1</a></div>
    <div class="swiper-slide">Slide 2</div>
    <div class="swiper-slide">Slide 3</div>
    <div class="swiper-slide">Slide 4</div>
    <div class="swiper-slide">Slide 5</div>
    <div class="swiper-slide">Slide 6</div>
    <div class="swiper-slide">Slide 7</div>
    <div class="swiper-slide">Slide 8</div>
    ...
  </div>
  <!-- If we need pagination -->
  <div class="swiper-pagination"></div>
</div>

<div class="swiper thumbnails-grid" slider_two>
  <!-- Additional required wrapper -->
  <div class="swiper-wrapper">
    <!-- Slides -->
    <div class="swiper-slide"><a>Slide 1</a></div>
    <div class="swiper-slide">Slide 2</div>
    <div class="swiper-slide">Slide 3</div>
  </div>
  <!-- If we need pagination -->
  <div class="swiper-pagination"></div>
</div>

Upvotes: 2

Related Questions