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!
…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.
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
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
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({
....
});
}