成功的ajax表单后重定向到

时间:2022-10-24 15:36:08

I've got a form with remote => true. And right now my controller looks like:

我有一个远程=> true的表单。现在我的控制器看起来像:

  # POST /items
  # POST /items.json
  def create
    @item = @store.items.build(params[:item])

    respond_to do |format|
      if @item.save
        format.html { redirect_to edit_admin_item_path(@item), :flash => {:success => "#{@item.name} was successfully created."} }
        format.js { render :js => "window.location.href = ('#{edit_admin_item_path(@item)}');"}
        format.json { render json: @item, status: :created, location: @item }
      else
        format.html { render action: "new" }
        format.js { render :partial => 'fail_create.js.erb', :locals => { :ajax_errors => @item.errors.full_messages } }
        format.json { render json: @item.errors, status: :unprocessable_entity }       
      end
    end
  end

Which works but feels very clumsy. It also doesn't allow me to use a flash notice, which is sad time indeed.

哪个有效,但感觉非常笨拙。它也不允许我使用闪光通知,这确实是悲伤的时间。

Ideally I feel like I should be able to simply use "format.js { redirect_to...} or check against the request headers and redirect_to. Sheesh!

理想情况下,我觉得我应该能够简单地使用“format.js {redirect_to ...}或检查请求标头和redirect_to。谢谢!

I'm not sure what the best solution is. Any advice would be super awesome, thanks in advance!

我不确定最好的解决方案是什么。任何建议都会超级棒,提前谢谢!

-- PS -- I know this has been asked somewhat before but to no avail: How to redirect after a successful AJAX form submission. There seems to many questions similar floating around, but no real solutions.

- PS - 我知道之前有人问过这个问题但无济于事:如何在成功提交AJAX表单后重定向。似乎有很多类似的问题浮出水面,但没有真正的解决方案。

3 个解决方案

#1


5  

I think it might be impossible. The response to a Ajax request is processed by XMLHttpRequest. If a 3xx response is returned, XMLHttpRequest will follow the redirect itself, if the URL is of same origin. No matter how you set the headers, the browser cannot be aware of that. So the only way could be changing window.location with some Javascript.

我想这可能是不可能的。对XML Ajax请求的响应由XMLHttpRequest处理。如果返回3xx响应,则XMLHttpRequest将遵循重定向本身,如果URL具有相同的来源。无论您如何设置标头,浏览器都无法意识到这一点。所以唯一的方法就是用一些Javascript来改变window.location。

#2


4  

I use a combination of Rails responders to generate my response messages and some content in my <action>.js file.

我使用Rails响应器的组合来生成我的响应消息和我的 .js文件中的一些内容。

The content of — say update.js would look something like this:

- 比如update.js的内容看起来像这样:

// Checks if the article slug has changed.
// If it has the entire page should be reloaded at that new location.
<%= reload_if_slug_changed @article, params[:id] %>

// Displays the flash notices
// See ApplicationHelper#js_flash_response
<%= js_flash_response %>

Where the different methods are defined in some helper (in my case my ApplicationHelper). The content of the different methods are as follows:

在一些帮助器中定义了不同的方法(在我的例子中是我的ApplicationHelper)。不同方法的内容如下:

def js_flash_response
  if flash.now[:notice].present?
    js = "$('#notice').html('#{flash.now[:notice]}').change();"
  elsif flash.now[:alert].present?
    js = "$('#alert').html('#{flash.now[:alert]}').change();"
  end
end

def reload_if_slug_changed object, expected_value
  "window.location.href = '#{url_for [:edit, object]}';" if object.slug != expected_value
end

The content of the flash messages are generated automatically by Rails responders and displayed with the now scope that deletes the from the flash hash, ensuring that if the user reloads (after the flash has been displayed) they will not reappear.

闪存消息的内容由Rails响应程序自动生成,并与删除闪存哈希值的现在范围一起显示,确保如果用户重新加载(在显示闪存之后),它们将不会再次出现。

I don't believe that you should ever make a form pointing to a restful create action a remote one, because you would always expect critical redirect, so in my case I only need to redirect if the url slug has changed.

我不相信你应该让表格指向一个遥远的创建动作,因为你总是期望重要的重定向,所以在我的情况下我只需要重新定向,如果url slug已经改变。

I hope that this helps. It's not a solution, but simply the way that I handled some of the same problems.

我希望这个对你有用。这不是一个解决方案,而只是我处理一些相同问题的方式。

Best regards.

最好的祝福。

#3


3  

Under your scenario, here's how I would inject javascript into the page from a controller action. After you've completed the logic section of your action insert something like this:

在您的场景下,这是我如何从控制器操作将javascript注入页面。在完成操作的逻辑部分后,插入以下内容:

render :update do |page|
    page << "javascript_here"
end

This should allow you to insert you window.location or create a javascript flash method and call it when your create method executes correctly.

这应该允许您插入window.location或创建一个javascript flash方法,并在create方法正确执行时调用它。

If you're looking to DRY up your controller actions, I would recommend looking into this Railscast about make_resourceful. Make_resourceful automagically performs each core activity for each action. It also allows you to tap into the hooks that they've created such as before :create, after :create, response_for :create, and after :create_fails. By using this gem, you can run code based on the success or failure of your methods and have finer grained control over them.

如果您想要干掉控制器操作,我建议您查看有关make_resourceful的Railscast。 Make_resourceful自动执行每个操作的每个核心活动。它还允许您利用他们创建的钩子,例如之前:create,after:create,response_for:create和after:create_fails。通过使用此gem,您可以根据方法的成功或失败运行代码,并对它们进行更细粒度的控制。

In addition to this, you should be able to initialize a create.js.erb and create_fails.js.erb in your view file, include a format.js without anything passed to it in your controller, and Rails will automagically run that file that contains javascript depending on if the controller action executed successfully.

除此之外,您应该能够在视图文件中初始化create.js.erb和create_fails.js.erb,在控制器中包含format.js而不传递任何内容,Rails将自动运行该文件包含javascript取决于控制器操作是否成功执行。

#1


5  

I think it might be impossible. The response to a Ajax request is processed by XMLHttpRequest. If a 3xx response is returned, XMLHttpRequest will follow the redirect itself, if the URL is of same origin. No matter how you set the headers, the browser cannot be aware of that. So the only way could be changing window.location with some Javascript.

我想这可能是不可能的。对XML Ajax请求的响应由XMLHttpRequest处理。如果返回3xx响应,则XMLHttpRequest将遵循重定向本身,如果URL具有相同的来源。无论您如何设置标头,浏览器都无法意识到这一点。所以唯一的方法就是用一些Javascript来改变window.location。

#2


4  

I use a combination of Rails responders to generate my response messages and some content in my <action>.js file.

我使用Rails响应器的组合来生成我的响应消息和我的 .js文件中的一些内容。

The content of — say update.js would look something like this:

- 比如update.js的内容看起来像这样:

// Checks if the article slug has changed.
// If it has the entire page should be reloaded at that new location.
<%= reload_if_slug_changed @article, params[:id] %>

// Displays the flash notices
// See ApplicationHelper#js_flash_response
<%= js_flash_response %>

Where the different methods are defined in some helper (in my case my ApplicationHelper). The content of the different methods are as follows:

在一些帮助器中定义了不同的方法(在我的例子中是我的ApplicationHelper)。不同方法的内容如下:

def js_flash_response
  if flash.now[:notice].present?
    js = "$('#notice').html('#{flash.now[:notice]}').change();"
  elsif flash.now[:alert].present?
    js = "$('#alert').html('#{flash.now[:alert]}').change();"
  end
end

def reload_if_slug_changed object, expected_value
  "window.location.href = '#{url_for [:edit, object]}';" if object.slug != expected_value
end

The content of the flash messages are generated automatically by Rails responders and displayed with the now scope that deletes the from the flash hash, ensuring that if the user reloads (after the flash has been displayed) they will not reappear.

闪存消息的内容由Rails响应程序自动生成,并与删除闪存哈希值的现在范围一起显示,确保如果用户重新加载(在显示闪存之后),它们将不会再次出现。

I don't believe that you should ever make a form pointing to a restful create action a remote one, because you would always expect critical redirect, so in my case I only need to redirect if the url slug has changed.

我不相信你应该让表格指向一个遥远的创建动作,因为你总是期望重要的重定向,所以在我的情况下我只需要重新定向,如果url slug已经改变。

I hope that this helps. It's not a solution, but simply the way that I handled some of the same problems.

我希望这个对你有用。这不是一个解决方案,而只是我处理一些相同问题的方式。

Best regards.

最好的祝福。

#3


3  

Under your scenario, here's how I would inject javascript into the page from a controller action. After you've completed the logic section of your action insert something like this:

在您的场景下,这是我如何从控制器操作将javascript注入页面。在完成操作的逻辑部分后,插入以下内容:

render :update do |page|
    page << "javascript_here"
end

This should allow you to insert you window.location or create a javascript flash method and call it when your create method executes correctly.

这应该允许您插入window.location或创建一个javascript flash方法,并在create方法正确执行时调用它。

If you're looking to DRY up your controller actions, I would recommend looking into this Railscast about make_resourceful. Make_resourceful automagically performs each core activity for each action. It also allows you to tap into the hooks that they've created such as before :create, after :create, response_for :create, and after :create_fails. By using this gem, you can run code based on the success or failure of your methods and have finer grained control over them.

如果您想要干掉控制器操作,我建议您查看有关make_resourceful的Railscast。 Make_resourceful自动执行每个操作的每个核心活动。它还允许您利用他们创建的钩子,例如之前:create,after:create,response_for:create和after:create_fails。通过使用此gem,您可以根据方法的成功或失败运行代码,并对它们进行更细粒度的控制。

In addition to this, you should be able to initialize a create.js.erb and create_fails.js.erb in your view file, include a format.js without anything passed to it in your controller, and Rails will automagically run that file that contains javascript depending on if the controller action executed successfully.

除此之外,您应该能够在视图文件中初始化create.js.erb和create_fails.js.erb,在控制器中包含format.js而不传递任何内容,Rails将自动运行该文件包含javascript取决于控制器操作是否成功执行。