Prześlij formularz w rails 3 w sposób Ajax (z jQuery)

79

Jestem początkującym w railsach i jQuery. Mam dwa oddzielne formularze na jednej stronie i chcę je przesłać osobno w sposób Ajax (z jQuery). Oto jak daleko dotarłem. Czy ktoś może dodać lub naprawić ten kod, aby działał. Używam Rails 3.1 i jQuery 1.6. Z góry dziękuję.

application.js

$(".savebutton").click(function() { 
    $('form').submit(function() {
         $(this).serialize();
    });
}); 

pierwsza forma:

<%=form_for :users do |f| %>
  <fieldset>
    <legend>Basic details</legend>
    <%= f.label :school %>
    <%= f.text_field :school,:size=>"45",:class=>"round",:id=>"school" %><br/>      
  </fieldset>
  <p><%= button_to "save and continue",{:class=>"savebutton"} %></p>
<%end%>

druga forma:

<%=form_for :courses do |c| %>
  <fieldset>
    <legend>Your current classes</legend>
    <label>class:</label><%= c.text_field :subject,:size=>"45",:class=>"round" %><br/>
  </fieldset>
  <p><%= button_to "save and continue",{:class=>"savebutton"} %></p>
<%end%>

SchoolController

class SchoolController < ApplicationController
  respond_to :json
  def create
    @school = current_user.posts.build(params[:school].merge(:user => current_user))
    if @school.save
      respond_with @school
    else
      respond_with @school.errors, :status => :unprocessable_entity
    end
  end
end

CourseController ma taki sam kształt jak SchoolController

katie
źródło

Odpowiedzi:

108

Chcesz:

  1. Zatrzymaj normalne zachowanie składania.
  2. Wyślij go przez AJAX do serwera.
  3. Uzyskaj odpowiedź i odpowiednio zmień rzeczy.

Poniższy kod powinien to zrobić:

$('form').submit(function() {  
    var valuesToSubmit = $(this).serialize();
    $.ajax({
        type: "POST",
        url: $(this).attr('action'), //sumbits it to the given url of the form
        data: valuesToSubmit,
        dataType: "JSON" // you want a difference between normal and ajax-calls, and json is standard
    }).success(function(json){
        console.log("success", json);
    });
    return false; // prevents normal behaviour
});
Johan
źródło
14
To nie zadziałało dla mnie w powyższej formie. Wydaje mi się, że to dlatego, że próbowałem wysłać wiadomość do zasobu, który używa tego samego adresu URL dla indeksu i tworzy metody w Railsach, co wymaga wymuszenia na żądaniu POST. Jeśli chcesz przesłać formularz wniosku o coś, co zostało zadeklarowane jako zasób routes.rb, musisz upewnić się, że używasz POST, a nie GET. Używając jQuery, po prostu dodaj type: 'POST'do $.ajaxrozmowy.
Eli Hooten,
Zaimplementowałem ten kod, ale wydaje się, że w rzeczywistości nie jest przesyłany. Muszę zawinąć go w $(CODE).submit();wywołanie, aby go wykonać, a następnie przesyła 2 posty. Jakieś pomysły?
pomyślany
Jak to zrobić, jeśli mam dość duży formularz? .serialize () spowoduje, że identyfikator URI żądania będzie zbyt długi podczas przesyłania.
zykadelic
Zobacz pierwszy komentarz, musisz wtedy wykonać żądanie POST. Więc dodaj type: 'POST'do wywołania ajax.
Johan
1
Ta odpowiedź naprawdę nie jest typowa dla szyn.
Mild Fuzz
58

Jeśli używasz :remote => truew swoich formularzach, możesz przesłać je za pomocą JavaScript za pomocą

$('form#myForm').trigger('submit.rails');
Łagodny Fuzz
źródło
4
Zostałem dziś ugryziony przez błąd w moim kodzie, więc wysyłałem posty, aby pomóc innym, którzy znaleźli się w takiej sytuacji jak moja. Miałem ukryte pole i przypadkowo (błąd kopiowania i wklejania) oznaczono je jako „wymagane”. Pole nie miało przypisanej wartości (powinno być przypisane statycznie przeze mnie). Ponieważ jest ukryty, nie ma artefaktu interfejsu użytkownika, na który szyny wskażą, aby go naprawić. Zamiast tego, kiedy formularz zostanie przesłany, railsy po cichu wywołają zdarzenie, na które jeśli nie zapiszesz się, nie będziesz wiedział, co się do cholery dzieje i dlaczego formularz nigdy nie został przesłany.
sob.
1
Przesyłanie formularza w trybie cichym przez AJAX zawsze ma ten problem w fazie rozwoju. Powinieneś być w stanie zobaczyć transakcję w swoich narzędziach programistycznych. Ponadto należy stosować AJAX dopiero po prawidłowym przesłaniu formularza.
Mild Fuzz
ciekawe, nie wiedziałem tego
Alain Goldman,
To najlepsza odpowiedź w przypadku UJS. Załóżmy, że masz formularz, który asynchronicznie pobiera token Stripe z usługi zdalnej po przesłaniu formularza. W funkcji wywołania zwrotnego Stripe otrzymujesz odpowiedź Stripe i teraz musisz ponownie przesłać formularz do akcji tworzenia Railsów. Jeśli zrobisz to za pomocą .ajax, nie będziesz w stanie obsłużyć danych o sukcesie i błędach w szablonie „create.js.erb”, tak jak powinieneś. Spróbuj użyć .submit()po raz drugi, a Twój remote => truei token uwierzytelniania zostaną utracone. .triggerskały, Twój formularz będzie #create tak, jak powinien, renderując „create.js.erb”
user3670743
@ user3670743 - dziękuję. czy jesteś w stanie rozwinąć tę kwestię?
BKSpurgeon
33

Preferowanym sposobem w Railsach 3 do wysyłania formularzy Ajax jest użycie Rails-ujs.

Zasadniczo pozwalasz Rails-ujs na wysyłanie AJAX za Ciebie (i nie musisz pisać żadnego kodu js). Następnie po prostu piszesz kod js, aby przechwycić zdarzenie odpowiedzi (lub inne zdarzenia) i rób swoje.

Oto kod:

Najpierw użyj opcji zdalnej w form_for, aby formularz był domyślnie przesyłany przez ajax:

form_for :users, remote:true do |f|

Następnie, gdy chcesz wykonać jakąś akcję na podstawie statusu odpowiedzi Ajax (np. Pomyślna odpowiedź), napisz logikę javscript w następujący sposób:

$('#your_form').on('ajax:success', function(event, data, status, xhr) {
  // Do your thing, data will be the response
});

Istnieje kilka wydarzeń, do których możesz się podłączyć.

lulalala
źródło
1
To samo na Rails 4, gdzie jest zainstalowany na domyślnym szablonie projektu. I nie zapomnij ustawić data: {type: 'text'}atrybutu zgodnie z opisem na api.jquery.com/jquery.ajax lub żądanie może się nie powieść z powodu błędu analizy JSON.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
13

Aby przesłać formularz przez AJAX, wystarczy, że przekażesz :remote => truego form_forpomocnikowi. Domyślnie rails 3.0.x używa prototypu js lib, ale możesz zmienić go na jquery za pomocą jquery-railsgem (który jest domyślny dla rails 3.1). bundle installgo, a następnie rails g jquery:installzastąpić pliki prototypów jquery.

Następnie wystarczy obsłużyć oddzwonienie. Spójrz na ten screencast

Bassneck
źródło
mam już bibliotekę jquery w swoim katalogu i usunąłem pliki prototypów, jquery działa, ale muszę tylko wysłać formularz z tego miejsca
katie
Instalator nie jest już potrzebny: stackoverflow.com/questions/7103437/ ...
Alex Moore-Niemi
2

jest to bardzo ważne w twoim żądaniu z Ajax, zatrzymaj domyślne zachowanie, wyślij remote: true w swoim form_for

<%= form_for :session, url: sessions_path, remote: true, html: { class: "form-signin" } do |f| %>

<% end %>

w twoim Ajax

$(".form-signin").on("submit", function(e) {
    $.ajax({
        url: $(this).attr('action'),
        data: $(this).serialize(),
        type: "POST",
        dataType: "json",
        success: function(response) {
            console.log(response)
        },
        error: function(xhr, textStatus, errorThrown) {}
    });
    e.preventDefault(); //THIS IS VERY IMPORTANT
});
Ezequiel García
źródło
0

Nic tutaj nie działało dla mnie, moim problemem było to, że biblioteka modalna jQuery uniemożliwiłaby przesyłanie moich formularzy za pośrednictwem danych zdalnych, gdybym przywołał okno modalne, ale znalazłem poprawkę.

Najpierw dodaj wtyczkę jQuery Form Plugin do katalogu javascript zasobów: http://malsup.github.io/jquery.form.js

Teraz zastąp metodę przesyłania dla swojego formularza. Na przykład możesz zrobić coś takiego:

= form_for @object, html: {class: "ajax_form_submit"}, authorization_token: true do |f|
  = f.text_input

javascript:

  $(document).on('ready page:load', function() {

    $(".ajax_form_submit").submit(function () {
      var form = $(this)
      form.ajaxSubmit({
        success: function (responseText, statusText, xhr) {
          console.log('success: ajax_form_submit')
        },
        error: function (jqXHR, statusText, errorThrown) {
          console.log('error: ajax_form_submit');
          console.log(jqXHR, statusText, errorThrown);
        }
      })
    })

  })
Mike Bethany
źródło