Отправить форму в рельсах 3 способом ajax (с jQuery)


79

Я новичок в рельсах и jQuery. У меня есть две отдельные формы на одной странице, и я хочу отправить их отдельно с помощью ajax (с помощью jQuery). Вот как далеко я зашел. Может ли кто-нибудь добавить или исправить этот код, чтобы он работал. Я использую Rails 3.1 и jQuery 1.6. Заранее спасибо.

application.js

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

первая форма:

<%=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%>

вторая форма:

<%=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 имеет ту же форму, что и SchoolController

Ответы:


108

Вы хотите:

  1. Прекратите нормальное поведение submit.
  2. Отправьте его через ajax на сервер.
  3. Получите ответ и внесите соответствующие изменения.

Код ниже должен сделать это:

$('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
});

14
У меня это не сработало в приведенной выше форме. Я считаю, что это произошло из-за того, что я пытался отправить сообщение на ресурс, который использует тот же URL-адрес для индекса и методов создания в Rails, для этого требуется, чтобы запрос был POST. Если вы хотите отправить запрос формы для чего-то, что было объявлено ресурсом routes.rb, вам необходимо убедиться, что вы используете POST, а не GET. Используя jQuery, просто добавьте type: 'POST'к $.ajaxвызову.
Эли Хутен

Я реализовал этот код, но на самом деле он не отправляется. Я должен обернуть его в $(CODE).submit();вызов, чтобы заставить его выполнить, затем он отправляет 2 сообщения. Есть идеи?
thinkpunch

Как мне это сделать, если у меня довольно большая форма? .serialize () вызовет ошибку URI запроса слишком длинный при отправке.
zykadelic 04

Смотрите первый комментарий, тогда вам нужно сделать POST-запрос. Так что добавьте type: 'POST'к ajax-call.
Johan

1
Это действительно не путь рельсов.
Mild Fuzz

58

Если вы используете :remote => trueв своих формах, вы можете отправить их с помощью JavaScript с помощью

$('form#myForm').trigger('submit.rails');

4
Сегодня меня укусила ошибка в коде, поэтому пишу, чтобы помочь другим, кто попал в такую ​​же ситуацию, как моя. У меня было скрытое поле, и случайно (ошибка копирования и вставки) поле было помечено как «обязательное». Поле не имеет присвоенного значения (должно быть статически присвоено мной). Поскольку он скрыт, нет артефакта пользовательского интерфейса, на который укажут рельсы, чтобы исправить. Скорее, когда форма отправлена, rails будет молча инициировать событие, на которое, если вы не подпишетесь, вы не узнаете, что, черт возьми, происходит и почему форма так и не была отправлена.
сб

1
При отправке формы в автоматическом режиме через AJAX всегда возникает эта проблема в разработке. Вы должны были видеть, что транзакция происходит в ваших инструментах разработчика. Кроме того, вы должны применять AJAX только после правильной отправки формы.
Mild Fuzz

интересно, я не знал этого
Ален Гольдман

Это лучший ответ с UJS. Допустим, у вас есть форма, которая асинхронно получает токен Stripe из удаленной службы при отправке формы. В вашей функции обратного вызова Stripe вы получаете ответ Stripe, и теперь вам нужно снова отправить форму в действие Rails create. Если вы сделаете это с помощью, .ajaxвы не сможете обрабатывать данные об успехах и ошибках в вашем шаблоне create.js.erb, как следовало бы. Попробуйте использовать .submit()второй раз, и ваш remote => trueтокен и токен авторизации потеряны. .triggerRock, ваша форма сделает его #create как следует, рендеринг create.js.erb
user3670743,

@ user3670743 - спасибо. Вы можете уточнить этот момент?
BKSpurgeon

33

В Rails 3 предпочтительный способ отправки формы ajax - использование Rails-ujs.

В основном вы позволяете Rails-ujs выполнять отправку ajax за вас (и вам не нужно писать какой-либо код js). Затем вы просто пишете js-код для захвата события ответа (или других событий) и делаете свое дело.

Вот код:

Во-первых, используйте удаленную опцию в form_for, чтобы форма по умолчанию отправлялась через ajax:

form_for :users, remote:true do |f|

Затем, когда вы хотите выполнить какое-либо действие на основе статуса ответа ajax (например, успешный ответ), напишите логику javscript следующим образом:

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

Есть несколько событий, к которым вы можете подключиться.


1
То же самое в Rails 4, где он устанавливается в шаблоне проекта по умолчанию. И не забудьте установить data: {type: 'text'}атрибут, как описано на api.jquery.com/jquery.ajax, иначе запрос может завершиться ошибкой из-за ошибки синтаксического анализа JSON.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

13

Чтобы отправить форму через AJAX, вы можете просто передать :remote => trueее form_forпомощнику. По умолчанию rails 3.0.x использует прототип js lib, но вы можете изменить его на jquery с помощью jquery-railsgem (что по умолчанию для rails 3.1). bundle installего, а затем rails g jquery:installзаменить файлы прототипов на jquery.

После этого вам просто нужно обработать обратный вызов. Взгляните на этот скринкаст


У меня уже есть библиотека jquery в моем каталоге, и я удалил файлы прототипов, jquery работает, но мне просто нужно отправить форму формы оттуда
Кэти

Установщик больше не нужен: stackoverflow.com/questions/7103437/…
Alex Moore-Niemi

2

это очень важно в вашем запросе с помощью ajax, чтобы остановить поведение по умолчанию, отправьте remote: true в вашей form_for

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

<% end %>

в вашем 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
});

0

У меня здесь ничего не работало, моя проблема заключалась в том, что модальная библиотека jQuery нарушала бы отправку моих форм через удаленные данные, если бы я открывал модальное окно, но я нашел исправление.

Сначала добавьте плагин формы jQuery в каталог javascript ваших ресурсов: http://malsup.github.io/jquery.form.js

Теперь переопределите метод отправки для вашей формы. Например, вы можете сделать что-то вроде этого:

= 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);
        }
      })
    })

  })
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.