Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Duplicate selectpicker with turbolinks #1413

Closed
Startouf opened this issue Jun 11, 2016 · 17 comments
Closed

Duplicate selectpicker with turbolinks #1413

Startouf opened this issue Jun 11, 2016 · 17 comments

Comments

@Startouf
Copy link

Startouf commented Jun 11, 2016

Using turbolinks 5, I am observing duplicate pickers when playing with the browser history

selectpicker

I am using a global $('.selectpicker').selectpicker('refresh');

The pickers are actually nesting into each other

<div class="btn-group bootstrap-select caret">
    <button class="btn dropdown-toggle btn-default" data-toggle="dropdown" type="button" data-id="sort_type" title="Trier par pertinence" aria-expanded="false">
        <div class="dropdown-menu open">
            <div class="btn-group bootstrap-select caret">
                <button class="btn dropdown-toggle btn-default" data-toggle="dropdown" type="button" data-id="sort_type" title="Trier par pertinence" aria-expanded="false">
                    <div class="dropdown-menu open">
                        <div class="btn-group bootstrap-select caret">
                            <button class="btn dropdown-toggle btn-default" data-toggle="dropdown" type="button" data-id="sort_type" title="Trier par pertinence" aria-expanded="false">
                                <div class="dropdown-menu open">
                                    <div class="btn-group bootstrap-select caret">
                                        <button class="btn dropdown-toggle btn-default" data-toggle="dropdown" type="button" data-id="sort_type" title="Trier par pertinence">
                                            <div class="dropdown-menu open">
                                                <select id="sort_type" class="caret selectpicker" name="sort_type" tabindex="-98">
@Startouf
Copy link
Author

A simple fix will just select the selectpickers which do not have the bootstrap-select class as direct parent

$('*:not(.bootstrap-select) > .selectpicker').selectpicker('refresh');

@aperkins81
Copy link

@Startouf This removes the duplicate, but renders the selectpicker unbinded - clicking/selecting no longer works... at least for multiselect.

@Startouf
Copy link
Author

Oh sorry about that, I don't use multiselect in the website I'm working on so I didn't check for bugs on that side. Any idea what causes that ?

@aperkins81
Copy link

aperkins81 commented Jun 28, 2016

I think it only affects Tubolinks v5.0.x.

Having created a new Rails 4.2 test app with the default version of turbolinks (2.53), back/forward works perfectly. But as soon as you update your gemfile to:

gem 'turbolinks', '~> 5.0.0.beta2', github: 'turbolinks/turbolinks-rails'

.. Then that's when the duplicates appear. Adding your suggestion fixes the duplicates but makes selectpicker unresponsive:

$('*:not(.bootstrap-select) > .selectpicker').selectpicker('refresh');

Test app:
git clone https://github.com/aperkins81/turbolinks-5-selectpicker.git && cd turbolinks-5-selectpicker && bundle install && rake db:migrate && rake db:seed && rails s -p 9999

then: http://localhost:9999/users/1/edit, click on 'Test link', then press the back button.

Will have a bit more of a look tomorrow.

@aperkins81
Copy link

OK, found a temporary(?) solution to this problem, needed to replace the contents of .bootstrap-select with .selectpicker then re-initialise selectpicker:

var remove = $('.bootstrap-select');
$(remove).replaceWith($(remove).contents('.selectpicker'));
$('.selectpicker').selectpicker();

aperkins81/turbolinks-5-selectpicker@9385f44

@aperkins81
Copy link

Even better, using the Turbolinks 5 turbolinks:before-cache :

$(document).on("turbolinks:load", function() { $('.selectpicker').selectpicker(); });
$(document).on("turbolinks:before-cache", function() {
  var remove = $('.bootstrap-select');
  $(remove).replaceWith($(remove).contents('.selectpicker'));
});

aperkins81/turbolinks-5-selectpicker@5dbab5c

@jimhj
Copy link

jimhj commented Jul 12, 2016

@aperkins81 It doesn't work for turbolinks 5.0.0

@jimhj
Copy link

jimhj commented Jul 12, 2016

My solution:

document.addEventListener 'turbolinks:load',  ->
  $(".selectpicker").selectpicker()

document.addEventListener 'turbolinks:before-cache',  ->
  $('.selectpicker').selectpicker('destroy').addClass('selectpicker')

@MaffooClock
Copy link

I was able to get around this altogether by invoking the plugin this way:

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

This preserves the auto-initialization behavior described in the README:

If you use a 1.6.3 or newer, you don't need to do anything else, as the data-api automatically picks up the <select>s with the selectpicker class.

@elsurudo
Copy link

elsurudo commented Feb 4, 2017

@MaffooClock I like your solution, but I had to use $(window).trigger('load.bs.select.data-api'); instead of $(this).trigger('load.bs.select.data-api');

@acrolink
Copy link

acrolink commented Mar 26, 2017

This is the solution that works perfectly for me:

$(document).on('turbolinks:load', function (e) {
	if (($("select.selectpicker").length > 0) && ($('.bs-caret').length == 0)) {
		$(".selectpicker").selectpicker();
	}
});

Update

Even better and more precise:

$(document).on('turbolinks:load', function () {
	$('.selectpicker').each(function (i, el) {
		if (!$(el).parent().hasClass('bootstrap-select')) {
			$(el).selectpicker('refresh');
		}
	});
});

@mldoscar
Copy link

mldoscar commented Jul 9, 2017

Same thing happened to me using materialize, and i made this fix for that, hope it helps:

HTML Code (with bug):

<div class="col s12 m3 field" id="combo_locale">
  <label for="page_locale">Idioma</label>
  <div class="select-wrapper">
    <span class="caret">▼</span><input type="text" class="select-dropdown" readonly="true" data-activates="select-options-17ab8bda-a896-b95d-14c4-82fb39f9a612" value="Español">
    <ul id="select-options-17ab8bda-a896-b95d-14c4-82fb39f9a612" class="dropdown-content select-dropdown ">
      <li class=""><span>English</span></li>
      <li class=""><span>Español</span></li>
    </ul>
    <div class="select-wrapper initialized">
      <span class="caret">▼</span><input type="text" class="select-dropdown" readonly="true" data-activates="select-options-36ae2844-e9cf-3ac7-ad4b-cf2dafb9b9fa" value="Español">
      <ul id="select-options-36ae2844-e9cf-3ac7-ad4b-cf2dafb9b9fa" class="dropdown-content select-dropdown ">
        <li class=""><span>English</span></li>
        <li class=""><span>Español</span></li>
      </ul>
      <div class="select-wrapper initialized">
        <span class="caret">▼</span><input type="text" class="select-dropdown" readonly="true" data-activates="select-options-de2ed84a-cff8-4816-e95f-54fc4b4f3d29" value="Español">
        <ul id="select-options-de2ed84a-cff8-4816-e95f-54fc4b4f3d29" class="dropdown-content select-dropdown ">
          <li class=""><span>English</span></li>
          <li class=""><span>Español</span></li>
        </ul>
        <select name="page[locale]" id="page_locale" class="initialized">
          <option value="en">English</option>
          <option selected="selected" value="es">Español</option>
        </select>
      </div>
    </div>
  </div>
</div>

JS Code (fixes html code with bugs above):

function fix_turbolink_materialize_combobox(combo_parent_container){
  main_element = $(combo_parent_container);
  subelements = main_element.find('.select-wrapper');
  if (subelements.length > 1) {
    preferred = subelements.last();
    main_element.append(preferred);
    main_element.find('.select-wrapper').first().remove();
  }
}

$(document).on('turbolinks:load', function(){
  fix_turbolink_materialize_combobox('#combo_locale');
})

Final result:

<div class="col s12 m3 field" id="combo_locale">
  <label for="page_locale">Idioma</label>
  <div class="select-wrapper initialized">
    <span class="caret">▼</span><input type="text" class="select-dropdown" readonly="true" data-activates="select-options-de2ed84a-cff8-4816-e95f-54fc4b4f3d29" value="Español">
    <ul id="select-options-de2ed84a-cff8-4816-e95f-54fc4b4f3d29" class="dropdown-content select-dropdown ">
      <li class=""><span>English</span></li>
      <li class=""><span>Español</span></li>
    </ul>
    <select name="page[locale]" id="page_locale" class="initialized">
      <option value="en">English</option>
      <option selected="selected" value="es">Español</option>
    </select>
  </div>
</div>

@matheussilvasantos
Copy link

matheussilvasantos commented Feb 18, 2018

I tried everything commented here, but it didn't work.

I was able to get around this altogether by not caching the page with the select.

I used this on the top of the page with select: <% provide(:no_cache, true) %>
I used this on application.html.erb:

<% if yield(:no_cache) %>
  <meta name="turbolinks-cache-control" content="no-cache">
<% end %>

@jingaworks
Copy link

2019 and no fix for this?

@pam81
Copy link

pam81 commented Jun 26, 2019

I used a combination of @matheussilvasantos and @ledsun and it work for me.
I'm using
"bootstrap": "4.3.1",
"bootstrap-select": "1.13.10",
"turbolinks": "5.2.0"

@OpakAlex
Copy link

2021, we think about Mars, but we can not fix js ;) hahha

@NicolasCARPi
Copy link
Collaborator

Turbolinks is no longer under active development.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests