我刚刚开始学习 Rails,非常感谢任何帮助。我在 form_for
上查看了大约 10 个关于 :remote => true
的教程,它们似乎都互相复制(同样令人困惑)。
本教程就是其中之一:http://tech.thereq.com/post/18910961502/rails-3-using-form-remote-true-with-jquery-ujs
我的网络应用程序几乎都在一个页面上,而我的“提交表单”位于弹出式灯箱内。这意味着 form_for 代码实际上在我的 index.html.erb 中。这也意味着为 index
创建了一个新的 @playlist 实例变量(而不是让它在 new
中)
我的最终目标是:
如果 @playlist.save
返回 true
,我想使用 :notice 将用户重定向到 root_path
。无需使用成功消息或类似信息更新表单。我想要在保存成功时进行硬重定向。
如果 @playlist.save
返回 false
,我想在 create.js.erb 中呈现代码,它将错误附加到灯箱表单中而不刷新页。 注意 很多教程似乎都想将整个表单重新渲染为 html,然后将内容替换到位。我宁愿(如果可以的话)只将错误发送到表单并插入它们,我认为重新呈现和替换整个表单似乎比实际情况更复杂。
截至目前,我的代码有点困惑,尤其是:
respond_to
block 。这是关于这里实际发生的事情的最大混淆点,我尝试了很多不同的代码但没有任何效果- 我不知道 create.js.erb 是否正确
- 我没有 create.html.erb - 我认为这是正确的,因为我只想重定向
我的表格第一行:
<%= form_for @playlist, :remote => true do |f| %>
我的整个 PlaylistsController
class PlaylistsController < ApplicationController
before_filter :load_genres, :only =>[:index, :user]
before_filter :new_playlist, :only => [:index, :new, :create]
def index
@playlists = Playlist.order('created_at DESC').page(params[:page]).per(30)
end
def new
end
def create
respond_to do |format|
if @playlist.save
# ???
format.html { redirect_to root_path, :notice => "Playlist submitted" }
else
# ???
format.js { render :js => @playlist.errors, :status => :unprocessable_entity }
end
end
end
def user
@playlists = Playlist.order('created_at DESC').where(:username => params[:username]).page(params[:page]).per(30)
end
def listen
playlist = Playlist.find(params[:playlist_id])
playlist.update_attribute(:listens, playlist.listens + 1)
render :nothing => true
end
private
def load_genres
@genres = Genre.order(:name)
end
def new_playlist
@playlist = Playlist.new(:title => params[:title], :url => params[:url], :description => params[:description])
end
end
create.js.erb
jQuery(function($) {
alert('createjs called');
$('#submit-form form').on('ajax:error', function(event, xhr, status, error){
var responseObject = $.parseJSON(xhr.responseText),
errors = $('<ul />');
$.each(responseObject, function(index, value){
errors.append('<li>' + value + '</li>');
})
$(this).find('.submit-playlist-errors').html(errors);
});
});
最佳答案
如果我没理解错的话,你有一个表单,你想用 flash
重定向,注意表单是否已保存。如果表单无效,您希望显示错误。
您可以将表单(或任何请求)以不同格式(通常是 html、json 和 js)发送到 Rails 应用程序。这是在您提供的网址中指定的。
playlist_path(@playlist)
# => /playlists/1
playlist_path(@playlist, :format => "json")
# => /playlists/1.json
playlist_path(@playlist, :format => "html")
# => /playlists/1.html
# ... etc
格式告诉 rails 要使用在 respond_to
block 中指定的哪种响应。
现在,如果很清楚,您必须决定使用哪种格式。
如果您指定js
格式,响应将被视为script
并执行。如果表单有效,您可以发送用户 javascript,将他们重定向到您想要的页面。如果表单无效,您可以修改 HTML 以显示错误消息。无需客户端代码。
respond_to do |format|
if valid
format.js { render "valid" }
else
format.js { render "invalid", :status => :unprocessable_entity }
end
end
# valid.js.erb
window.location = <%= your_path %>
# invalid.js.erb
// whatever to display errors
当您使用 json
时,如果表单无效,您可以返回重定向 url 以重定向用户或错误。请注意,此解决方案需要客户端的 Javascript 来处理它。
# controller
respond_to do |format|
if valid
format.json { render :json => your_path }
else
format.json { render :json => @object.errors, :status => :unprocessable_entity }
end
end
# client side javascript
$("form")
.on("ajax:success", function(event, data, status, response) {
window.location = data
})
.on("ajax:error", function(event, response, error) {
// logic to handle errors
})
您还可以使用html
格式(通过将格式设置为html
或根本不指定格式)。但是,如果您使用 :remote => true
,您将不得不像对待 json
(具有客户端 javascript)一样对待它。如果您使用 redirect_to
作为响应,它将重定向请求,而不是您的用户。
我不确定在重定向用户后是否显示 flash 消息,但您可以这样尝试:
respond_to do |format|
if valid
format.html {
flash[:notice] = "Playlist submitted"
render :json => your_path }
else
format.html { render :json => @object.errors, :status => :unprocessable_entity }
end
end
# client side javascript
//...
希望这会擦干您的 respond_to
block 。
关于jquery - :remote => true confusion with form_for,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12568887/