Richlewis
Richlewis

Reputation: 15384

Reinitialize Slick js after successful ajax call

I am using Slick for a carousel implementation and everything works fine when the pages loads.What I am trying to achieve is that when i make an Ajax call to retrieve new data I still want the slick carousel implementation, at the moment i lose it.

I have put the call for slick into a function

function slickCarousel() {
  $('.skills_section').slick({
    infinite: true,
    slidesToShow: 3,
    slidesToScroll: 1
  });
}

and then I call the function within my success callback

$.ajax({
    type: 'get',
    url: '/public/index',
    dataType: 'script',
    data: data_send,
      success: function() {
        slickCarousel();
      }
   });

But the function isn't being called. How can I reinitialize this js?

Upvotes: 32

Views: 157060

Answers (13)

Shashank Bhatt
Shashank Bhatt

Reputation: 857

Although, above answers are correct, there is one more problem regarding showing new slides with updated/new data after array has been updated and then need to refresh the slick slider instance.

If we don't do like this, then somehow slick keeps showing older data which was bounded there before updating the array even if the array is already updated.

So the code with newer frameworks available and ES6 approach might look something like this.

Let's say we are showing array of data via loop in modern library like vue, react, angular or alpine js and we have array of shops to show as a slider.

Each time someone triggers some action, array(and eventually dom) is updated but we have to manually tell slick slider to update the slides data as per the data in the new array. here we have data in the form of shops array.

  {
        shops: [],
        init() {
            let self = this;
            // watch for your data and provide callback function after it has been updated
            // this $watch is example from alpine js but similar could be available in other framrworks
            self.$watch('shops',(currentShops,oldShops) => {
                //currentshops holds the new value of shops after update
                //oldShops holds older value before update

                //first remove all slides that were attached with slick before shops array was updated (sorted for example)
                $('#shops-section-slider.slick-initialized').slick('slickRemove', null, null, true);
                //After this, add new slides after shops has been updated(sorted)
                // via template that accepts shop as an argument
                currentShops.forEach(function(shop,index) {
                    $('#shops-section-slider.slick-initialized').slick('slickAdd', self.getSliderTmpl(shop));
                })
                //after adding and removing is completed, 
                //finally just call refresh to prevent reinit entirely.
                $('#shops-section-slider.slick-initialized').slick('refresh');
            })
            //shopsPromise only does slider creation and other things when data has been updated in dom.
            shopsPromise.then(function(data) {
                //update shops here via data that has been recieved
                shops.push(data)
            }).then(function() {
                //crate slider after promise is resolved
                $('#shops-section-slider').not('.slick-initialized').slick({
                    //your slick settings
                })
            });
        },
        
        getSliderTmpl(shop) {
            return `<div class="col-12 col-md-6 col-lg-4 col-xl-4 d-flex flex-column shops-section">
                <div class="row flex-grow-1 flex-column flex-xxl-row">
                    <div class="col-12 col-xxl-6">
                        <div class="shops-img position-relative">
                            <strong class="shops-title-card d-block d-xxl-none">${shop.whateveravailable}</strong>
                        </div>
                    </div>
                    
                </div>
            </div>`;
        }
    }

and inside the html, we even don't need the <template> element which is used as looping in alpine js as it creates incorrect width and issues due to one more slides there so we can omit that, and thus managing entire slider data and template both from js only.

<div class="row shops-section-wrapper" id="shops-section-slider"></div>

Upvotes: 0

Lex Jad
Lex Jad

Reputation: 81

Slick Version: 1.8.0

 function getSliderSettings() {
                return {
                    slidesToShow: 3,
                    slidesToScroll: 1,
                    loop: true,
                    arrows: true,
                    dots: false,
                }
            }
    
    
    $.ajax({
            type: 'get',
            url: '/public/index',
            dataType: 'html',
            data: some_data,
            success: function(response) {
                    $('[data-role="slick-slider"]').slick('unslick');
                    $('[data-role="slick-slider"]').html($(response).html());
                    $('[data-role="slick-slider"]').slick(getSliderSettings());
              }
        });

Upvotes: 0

Junaid
Junaid

Reputation: 4926

I was facing an issue where the Slick carousel wasn't refreshing on new data instead it was appending new slides to the previous ones, I found a solution that solved my problem, it's very simple.

TL;DR
Try passing unslick, then assign your new data which is being rendered inside slick carousel, and then initialize slick again. these were the steps for me:

jQuery('.class-or-#id').slick('unslick');
myData = my-new-data;
jQuery('.class-or-#id').slick({slick-options});

Notes:
Check the slick.js website for syntax just in case. Also, make sure you are not using unslick before slick is even initialized. What that means is, simply initialize like this the very first ajax call
jquery('.my-class').slick({slick-options})
And once it's initialized then follow the above steps. You might wanna use if-else.

Upvotes: 4

Lahiru Dilshan
Lahiru Dilshan

Reputation: 41

Try this code, it helped me!

$('.slider-selector').not('.slick-initialized').slick({
  dots: true,
  arrows: false,
  setPosition: true
});

Upvotes: 4

Dmitry Shulga
Dmitry Shulga

Reputation: 618

Here we go, guys! It helped me

$('.slick-slider').not('.slick-initialized').slick({
   infinite: false,
   slidesToShow: 1,
   slidesToScroll: 1,
   dots: true,
   arrows: false,
   touchThreshold: 9
});

Upvotes: 3

Mihir Bhatt
Mihir Bhatt

Reputation: 3155

$('#slick-slider').slick('refresh'); //Working for slick 1.8.1

Upvotes: 18

Tijan Manandhar
Tijan Manandhar

Reputation: 332

After calling an request, set timeout to initialize slick slider.

var options = {
    arrows: false,
    slidesToShow: 1,
    variableWidth: true,
    centerPadding: '10px'
}

$.ajax({
    type: "GET",
    url: review_url+"?page="+page,
    success: function(result){
        setTimeout(function () {
            $(".reviews-page-carousel").slick(options)
        }, 500);
    }
})

Do not initialize slick slider at start. Just initialize after an AJAX with timeout. That should work for you.

Upvotes: -1

Chirag Prajapati
Chirag Prajapati

Reputation: 539

The best way is you should destroy the slick slider after reinitializing it.

function slickCarousel() {
  $('.skills_section').slick({
    infinite: true,
    slidesToShow: 3,
    slidesToScroll: 1
  });
}
function destroyCarousel() {
  if ($('.skills_section').hasClass('slick-initialized')) {
    $('.skills_section').slick('destroy');
  }      
}

$.ajax({
  type: 'get',
  url: '/public/index',
  dataType: 'script',
  data: data_send,
  success: function() {
    destroyCarousel()
    slickCarousel();
  }
});

Upvotes: 20

Tejas Kemkar
Tejas Kemkar

Reputation: 65

The best way would be to use the unslick setting or function(depending on your version of slick) as stated in the other answers but that did not work for me. I'm getting some errors from slick that seem to be related to this.

What did work for now, however, is removing the slick-initialized and slick-slider classes from the container before reinitializing slick, like so:

function slickCarousel() {
    $('.skills_section').removeClass("slick-initialized slick-slider");
    $('.skills_section').slick({
        infinite: true,
        slidesToShow: 3,
        slidesToScroll: 1
    });
}

Removing the classes doesn't seem to initiate the destroy event(not tested but makes sense) but does cause the later slick() call to behave properly so as long as you don't have any triggers on destroy, you should be good.

Upvotes: 3

A.Clifford
A.Clifford

Reputation: 76

I had to unslick the carousel before the ajax call starts, but you can't do that until there is already a slick carousel. So, I set a variable to 0 and only run unslick after it changed

var slide = 0
if(slide>0)      
$('#ui-id-1').slick('unslick');

        $.ajax({
            //do stuff, here
        },
        success: function( data ) {

            $('#ui-id-1').slick();
            slide++;

        }

Upvotes: 3

Minoru
Minoru

Reputation: 281

You should use the unslick method:

function getSliderSettings(){
  return {
    infinite: true,
    slidesToShow: 3,
    slidesToScroll: 1
  }
}

$.ajax({
  type: 'get',
  url: '/public/index',
  dataType: 'script',
  data: data_send,
  success: function() {
    $('.skills_section').slick('unslick'); /* ONLY remove the classes and handlers added on initialize */
    $('.my-slide').remove(); /* Remove current slides elements, in case that you want to show new slides. */
    $('.skills_section').slick(getSliderSettings()); /* Initialize the slick again */
  }
});

Upvotes: 28

jdavid.net
jdavid.net

Reputation: 751

This should work.

$.ajax({
    type: 'get',
    url: '/public/index',
    dataType: 'script',
    data: data_send,
    success: function() {
        $('.skills_section').slick('reinit');
      }
});

Upvotes: 15

web-nomad
web-nomad

Reputation: 6003

Note: I am not sure if this is correct but you can give it a try and see if this works.

There is a unslick method which de-initializes the carousel, so you might try using that before re-initializing it.

$.ajax({
    type: 'get',
    url: '/public/index',
    dataType: 'script',
    data: data_send,
    success: function() {
        $('.skills_section').unslick();  // destroy the previous instance
        slickCarousel();
      }
});

Hope this helps.

Upvotes: 4

Related Questions