2017-10-13 41 views
9

próbuję wdrożyć modele zagnieżdżone, tutaj jest zapis pliku trasa:Jak zaimplementować zdalny: true function without link_to?

resources :projects do 
    resources :instances 
end 

Poniżej znajduje się fragment regulatora projektu:

# GET /projects/new 
def new 
    @project = Project.new 
    @project.instances.build 
end 

i widok forma projektu:

<%= simple_form_for(@project) do |f| %> 
    ... 
    <%= label_tag :instance_count, "Instance Count" %> 
    <%= select_tag :instance_count, options_for_select([0, 1, 2, 3, 4, 5], 0) %> 
    ... 
<% end %> 

Teraz, gdy zmieniam liczbę wystąpień instancji, muszę wyświetlać pola instancji te wiele razy poniżej powyższego formularza. Oto kod częściowego za to:

<%= form.simple_fields_for :instances do |i| %> 
    ... 
<% end %> 

Zasadniczo muszę zadzwonić <%= render 'instances/form', form: f %> z pliku javascript projektu. Powinno działać jak link z opcją remote: true. Ale w tym przypadku nie ma łącza, ale w przypadku zdarzenia zmiany należy wyświetlić formularz. Jak mam to wdrożyć?

+0

po kliknięciu '@project [: instance_count]' i zmienić numer, który chcesz wyświetlić inną liczbę 'instances' pól wejściowych? Czy to wymaga AJAX? może wystarczy tylko wsłuchać się w to wydarzenie click w tym div, aby dołączyć nowy div na tej stronie, a kiedy przesłać formularz, upewnij się, że przesyłka działa dla tych pól .... Mam na myśli opublikowanie odpowiedzi .. Dodawanie pola wejściowe są trochę skomplikowane, ponieważ formularz ma 'token', który unika CSRF, także przesłanie musi być wykonane może z' Javascript' i będziesz musiał utworzyć żądanie jquery '.post()' –

+0

Twój trigger to kliknięcie na '<% = select_tag: instance_count, options_for_select ([0, 1, 2, 3, 4, 5], 0)%>' so '$ ('# select_tab'). click (// dodaj wejście div na stronie w zależności od wyniku div .value()); ', nie ma interakcji serwera. Następnie musisz wykonać żądanie 'post' w pliku javascript za pomocą tej funkcji https://api.jquery.com/jQuery.post/ –

Odpowiedz

0

Musisz raz wywołać kod serwery, ponieważ kod instances/form zawiera kod, który może być renderowany tylko na serwerze.
Najpierw musisz wykonać wywołanie ajax (np. Instance_new_path), a następnie musisz wyrenderować formularz w tym widoku (instance_new.js.erb).

przykład .js.erb

$("#new_form").html("<%= escape_javascript(render partial: 'instances/form') %>"); 
+0

Przekazanie obiektu formularza jest tutaj nieco skomplikowane (znajduję) - w jaki sposób udostępniasz to częściowemu? – SRack

+0

To musi być zrobione na kontrolerze, również specjalizacja może być wykonana po dostarczeniu pełnego kodu. –

0

Standard to zrobić częściowy zwany app/views/instances/_instance_fields.html.erb. Następnie możesz po prostu załadować go do formularza i ukryć.

<%= simple_form_for(@project) do |f| %> 
    <%= render 'instances/_instance_fields %> 
<% end %> 

pokrywa _instance_fields częściowego z jakiegoś pojemnika, jak <fieldset class='instance_fields' style='display:none'>. Ponadto nie powinieneś używać tam obiektu formularza, wystarczy wejść tam z tekstem text_field_tag ​​/ checkbox_tag. Następnie, gdy potrzebujesz dodać więcej instancji, po prostu skopiuj te ukryte fragmenty tyle razy, ile potrzebujesz, i ustaw odpowiednie nazwy wejść (aby były dostępne dla accepts_nested_attributes_for).

Ping mnie, aby podać więcej szczegółów i pomocy. To podejście zostało zastosowane w rzeczywistym projekcie. Pożarowe wywołanie ajax za każdym razem, gdy trzeba dodać więcej instancji, nie jest w ogóle zoptymalizowane.

+0

Już używam '<% = render 'instances/form', form: f%>' .. –

+0

Musisz przechowywać ten element w jakimś ukrytym szablonie i skopiować ten szablon dla każdej nowej instancji. Po skopiowaniu musisz ustawić własne nazwy za pomocą javascript. Kilka konkretnych uwag, które nie działają w podejściu, które ci dałem. Nie powinieneś używać atrybutu 'od'. Jest absolutnie bezużyteczne w przypadku szablonu, ponieważ nadal będziesz musiał obsługiwać wejściowe atrybuty 'name' ręcznie w javascript – AntonTkachov

0

Proponuję użyć https://github.com/nathanvda/cocoon

Albo można użyć podobnego Aproach: renderowanie częściowe w początkowej postaci (z display: none), następnie wyjąć i zapisać pola częściowe z js i sklonować je tworzyć, gdy selektor jest trafiony .

0

Utwórz plik .js i załadować go wewnątrz projects/new.html.erb, który będzie wykonywał, gdy nastąpiła zmiana w select wartości i tworzy post prośbę do instances/new kontrolera, który będzie świadczyć instances/new.js.erb każdym razem, gdy jest trafiony.

# GET /instances/new 
def new 
    @f = Instance.new 
end 

przypadki/new.js.erb

$('#instance-form-wrapper').append(<% escape_javascript(render 'instances/form', form: @f) %> 

obciążenia.js

$(document).on('change', 'select#some-id-name', function(){ 
    var v = $(this).val(); 
    $('#instance-form-wrapper').html('') ; 
    while(v--) $.post('/instances/'); 
}) 

Choć zalecana nie użycie takiego. Zamiast tego wczytaj jedno pole instance w swoim kodzie, ukryj je, ponieważ masz już instance dostępny w swoim project. Poza tym nie potrzebujesz nowych danych za każdym razem, gdy je renderujesz. Po prostu wybierając wartość 1 możesz show swoje pole instance, a jeśli wartość to > 1 możesz użyć clone, aby skopiować dalej.