Slashek / bootstrap-select-rails

bootstrap-select-rails
MIT License
62 stars 54 forks source link

Do not work with Turbolinks 5 well #31

Open ledsun opened 6 years ago

ledsun commented 6 years ago

Problem

bootstrap-select depends on the load events of the window.

https://github.com/silviomoreto/bootstrap-select/blob/master/js/bootstrap-select.js#L1840

  $(window).on('load.bs.select.data-api', function () {
    $('.selectpicker').each(function () {
      var $selectpicker = $(this);
      Plugin.call($selectpicker, $selectpicker.data());
    })
  });

But the load events of the window is not fired in page transitions with Turbolinks 5.

Reference: https://github.com/silviomoreto/bootstrap-select/issues/1413

Resolve

We relay the 'turbolinks:load' events of the document to the load events of the window.

For example:

$(document).on('turbolinks:load', function() {
   $(window).trigger('load.bs.select.data-api');
});

Suggestion

I think it is a good idea to append above code into the vendor/assets/javascripts/bootstrap-select.js in this gem. Because this gem is to use bootstrap-select with the Ruby on Rails.

CodyFitzpatrick commented 5 years ago

While I'm not using this gem in my Rails 5 app, Bootstrap 4 <select>s break when turbolinks loads pages from cache. @ledsun's mentioned fix work in these situations, without duplicating dropdowns like $('select').selectpicker(); happened to do.

Hopefully this can help someone else.

cigano commented 5 years ago

This solution doesn't work for version 1.13.8. Had to disable Turbolinks completely.

At any <div> from you layout, add data-turbolinks="false".

ledsun commented 5 years ago

I made a sample application that uses version 1.13.8. This solution is still working well. https://github.com/ledsun/sample-application-for-verifying-the-solution-for-bootstrap-select-rails-to-work-with-Turbolinks-5.

cesc1989 commented 5 years ago

Also didn't work in my case.

pam81 commented 5 years ago

same issue I'm using "bootstrap": "4.3.1", "bootstrap-select": "1.13.10", "turbolinks": "5.2.0"

eredi93 commented 5 years ago

@Slashek are you planning to support turbolinks? I saw you closed https://github.com/Slashek/bootstrap-select-rails/pull/32 without offering a workaround. should we assume turbolinks is not supported? If so should you update the README?

xxEoD2242 commented 4 years ago

@ledsun's solution is working for:

Also, try adding 'ready' for the $(document).on() selection. Example below:

$(document).on('ready turbolinks:load', function() {
    $(window).trigger('load.bs.select.data-api');
});

Having both ready and turbolinks:load has helped me get past all of the JS/Turbolinks issues I have had.

romanbsd commented 4 years ago

It breaks when doing "back" in the browser.

romanbsd commented 4 years ago

This is the workaround for going "back":

$(document).on('turbolinks:before-cache', function() {
    const $picker = $('.selectpicker');
    const picker = $picker.data('selectpicker');
    if (picker) {
        picker.destroy();
        $picker.addClass('selectpicker');
    }
});
wulman16 commented 4 years ago

@romanbsd Your solution worked for me to an extent, but when navigating my application using Turbolinks, the selectpicker element would appear noticeably later than the rest of the page.

My solution ended up using the data-turbolinks-permanent attribute from the Turbolinks API (Persisting Elements Across Page Loads):

$(document).on('ready turbolinks:load', function() {
  $(window).trigger('load.bs.select.data-api');
}); 
<div id="selectpicker-parent" data-turbolinks-permanent></div>
OpakAlex commented 3 years ago

This is the workaround for going "back":

$(document).on('turbolinks:before-cache', function() {
    const $picker = $('.selectpicker');
    const picker = $picker.data('selectpicker');
    if (picker) {
        picker.destroy();
        $picker.addClass('selectpicker');
    }
});

Thanks man!

tkuisma commented 3 years ago

This is the workaround for going "back":

That solution works, but only for one selectpicker. When there are multiple pickers, it is better to handle them all.

$(document).on('turbolinks:before-cache', function() {
    $('.selectpicker').each(function (i, el) {
        const picker = $(el).data('selectpicker');
        if (picker) {
            picker.destroy();
            $(el).addClass('selectpicker');
        }
    });
});

But with this solution the problem is that the selected values are lost when going "back". So I'm trying to find a way to first store selected values and then restore them after the destroy call.

adomigold commented 2 years ago

This solution helped me out

function jsReload() { $('.selectpicker').selectpicker(); $('.flatpickr').flatpickr(); } $(document).ready(jsReload); $(document).on('page:load', jsReload);

Hope it will help you to.