bootstrap-select-rails icon indicating copy to clipboard operation
bootstrap-select-rails copied to clipboard

Do not work with Turbolinks 5 well

Open ledsun opened this issue 6 years ago • 13 comments

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.

ledsun avatar Mar 08 '18 01:03 ledsun

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.

CodyFitzpatrick avatar Feb 08 '19 21:02 CodyFitzpatrick

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".

cigano avatar Apr 07 '19 05:04 cigano

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.

ledsun avatar May 17 '19 09:05 ledsun

Also didn't work in my case.

  • bootstrap-select-rails (1.13.8)
  • rails (5.2.3)

cesc1989 avatar May 27 '19 22:05 cesc1989

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

pam81 avatar Jun 26 '19 21:06 pam81

@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?

eredi93 avatar Oct 03 '19 20:10 eredi93

@ledsun's solution is working for:

  • Turoblinks (5.2.1)
  • Rails (6.0.0)
  • Bootstrap (4.3.1)
  • bootstrap-select (1.13.8)

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.

xxEoD2242 avatar Dec 20 '19 15:12 xxEoD2242

It breaks when doing "back" in the browser.

romanbsd avatar Apr 26 '20 09:04 romanbsd

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');
    }
});

romanbsd avatar May 01 '20 20:05 romanbsd

@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>

wulman16 avatar Jul 16 '20 16:07 wulman16

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!

OpakAlex avatar Mar 18 '21 20:03 OpakAlex

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.

tkuisma avatar Mar 19 '21 09:03 tkuisma

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.

adomigold avatar Feb 21 '22 13:02 adomigold