$(document).ready(function() { ... }

Cześć,

Rails 5.1.1, Turbolink 5, Dodany gem ‘jquery-turbolinks’ skonfigurowany application.js.

Mam stronkę na której ładuję partiala, oprogramowałem dodawanie rekordów do tabeli podrzędnej z wykorzystaniem accepts_nested_attributes_for. Dodałem w partialu:

<script>
$(document).ready(function() {
  $('.select2user').select2({

    ....

  });

});
</script>

…gdyż wykorzystuję w tym partialu Select2.

Wszystko śmiga świetnie! :slight_smile:

…ale gdy kod zawarty w <script>...</script> przeniosę do jakiegoś pliku w podkatalogu /app/assets/javascripts to komponent Select tworzy mi się tylko przy otwieraniu strony (jeżeli mam kilka rekordów podrzędnych), a nie chce przy dodawaniu kolejnego partiala. :frowning:

Powtórzę:
Jeżeli kod mam umieszczony w parialu pomiędzy znacznikami <script></script>, to wszystko jest super, a po wyniesieniu tego kodu do osobnego pliku, to tylko w czasie ładowania się odpala, a nie chce gdy dodaję kolejny partial.

Macie jakieś pomysły?

Z tego co wiem to turbolinks działa w ten sposób, że tylko za pierwszym razem są wczytywane assety, więc i JS z nich, co prowadzi do tego, że selecty tylko z pierwszego partiala są zamieniane na select2. Wydaję mi się, że:

document.addEventListener('turbolinks:load', function() {
  $('.select2user').select2({
    ....
  });
});

w pliku powinno sprawę rozwiązać.

Niestety. Ładuje za pierwszym razem, ale gdy dodaję partiala, to nie wyświetla mi tego select2 :frowning:

Może źle zrozumiałem - ten drugi partial jest ładowany jakoś przez ajax, po załadowaniu strony?

ładowanie partiala:
Fragment _form:

...
      <div class='accessorizations clearfix'>
        <div class='accessorizations-sub-form'>
          <%= f.fields_for :accessorizations do |accessorization_form|  %>
            <%= render 'accessorization_fields', f: accessorization_form %> 
          <% end %>
        </div>
        <%= link_to_add_fields("[Add Accessorization]", f, :accessorizations) %>
      </div>
...

accessorizations - model tabeli podrzędnej
helper do link_to_add_fields

module ApplicationHelper

  def link_to_add_fields(name, f, association, opts={})
    # creaate a new object given the form object, and the association name
    new_object = f.object.class.reflect_on_association(association).klass.new

    # call the fields_for function and render the fields_for to a string
    # child index is set to "new_#{association}, which would then later
    # be replaced in in javascript function add_fields
    fields = f.fields_for(association,
        new_object,
        :child_index => "new_#{association}") do |builder|
      # render partial: _task_fields.html.erb
      render(association.to_s.singularize + "_fields", f: builder)
    end

    # call link_to_function to transform to a HTML link
    # clicking this link will then trigger add_fields javascript function
    link_to_function(name,
      h("add_fields(this,
        \"#{association}\", \"#{escape_javascript(fields)}\");return false;"),
      class: 'btn btn-success pull-right')
  end

  def link_to_function(name, js, opts={})
    link_to name, '#', opts.merge({onclick: js})
  end
  
end

No musisz jakoś monitorować załadowanie partiala, jest dajesz słuchacza onready lub turbolinks:load to Ci przecież nie obsłuży jakiejś randomowej funkcji. Podpowiem, że w Twoim przypadku jest to add_fields.

To może jaśniej mi wytłumacz.
Podpowiedź, że jest to add_fields niewiele mi daje.

Ponadto nadal nie rozumiem, dlaczego ten “słuchacz” (onredy) działa, gdy kod jest umieszczony w partialu, a nie, gdy jest wyniesiony do pliku?

to w sumie podstawy tego chorego języka którym jest js :wink:
chodzi o to że jak wrzucasz w pliku to onready działa sobie w tym kontekście, a nie w kontekście całej strony - tak jak to jest kiedy siedzi w assetach.
w add_fields() masz pewnie ajaxa co odpytuje serwer i podstawia w odpowiednie miejsce, to albo tam musisz odpalić inicializację select2 albo na przykład

    ...
    link_to_function(name,
      h("add_fields(this,
        \"#{association}\", \"#{escape_javascript(fields)}\"); init_select2(this); return false;"),
      class: 'btn btn-success pull-right')
  end

i wtedy w assetach

function init_select2(input) {
  $(input).select2({
    ....
  });
}

Dzięki.