AJAX表单(使用simple_form)保留错误验证

时间:2012-04-07 01:44:05

标签: jquery ruby-on-rails ajax

这可能是我提出的更困难的问题之一,但我已经被困了几天,我认为最好是从更有经验的rails社区获得支持。

我正在制作一个虚拟应用程序,大致遵循本指南...... ajax/jquery tutorial ...

制作我自己的自定义,指南帮助我创建了一个品牌" (包括嵌套模型"模型","子模型","样式")提交表单(使用simple_form)和品牌列表在同一页面上..这完美地运作,并且强制执行验证(对于我的模型)。但是,当我将表单和品牌列表放在同一页面上时,我会丢失在提交失败时出现的整洁的内联验证错误(请参见下图)。无法让内联错误发挥作用让我意识到我还有更多关于渲染的知识......这就是为什么我注重找到这个问题的答案

enter image description here

......这里是列表:

enter image description here

以下是索引操作的控制器:

  def index

    #This is for the product listing

    @brands = Brand.all.reverse 

    #This is for the form   

    @brand = Brand.new
    @model = Model.new
    @submodel = Submodel.new
    @style = Style.new

    respond_to do |format|
      format.html
    end
  end

上面的表单创建了在嵌套提交表单中使用的品牌,型号,子模型和样式...下面是表单的代码:

<%= simple_form_for @brand, :html => { :class => 'form-horizontal' }, :remote => true do |m| %>

  <fieldset style = "margin-top:34px;">
    <legend></legend>
    <%= m.input :name, :label => 'Brand' %>         
    <%= m.simple_fields_for :models, @model do |p| %>    
      <%= p.input :name, :label => 'Model' %>
      <%= p.simple_fields_for :submodels, @submodel do |s| %>
        <%= s.input :name, :label => 'Submodel' %>
        <%= s.simple_fields_for :styles, @style do |ss| %>
          <%= ss.input :name, :label => 'Style' %>
        <% end %>
      <% end %>
    <% end %>

    <div class="form-actions">
      <%= m.submit nil, :class => 'btn btn-primary' %>
      <%= link_to 'Cancel', brands_path, :class => 'btn' %>
    </div>
  </fieldset>
<% end %>

现在您可以看到我正在使用:remote => true ...我希望表单能够创建新的&#34;品牌&#34;,或者表单重新加载内联验证错误。目前我的创建动作如下:

def create
    @brand = Brand.new(params[:brand])

    respond_to do |format|
      if @brand.save
        format.html { redirect_to brands_url, notice: 'Brand was successfully created.' }
        format.json { render json: @brand, status: :created, location: @brand }
        format.js
      else
        format.html { render action: "index" }
        format.json { render json: @brand.errors, status: :unprocessable_entity }
        format.js { render 'reload' }
      end
    end
  end

if @brand.save下显示的代码似乎有用..但下面的代码&#34;否则&#34;没有按照我喜欢的方式工作。那么当@brand不保存时会发生什么?我相信索引操作中的代码正在运行,然后@brand.errors转换为json(我假设是为了simple_form验证错误),然后正在运行reload.js.erb ..

在尝试重新加载表单时(带有验证错误)我将行$("#entryform").load(location.href+" #entryform>*","");放入reload.js.erb ...当我将无效数据放入我的表单时reload.js.erb被调用,但所有发生的情况是表单字段重新加载空白,而不是输入数据和内联验证错误。

我希望我在这里提供足够的信息以获得帮助。真的在这个问题上挣扎。谢谢!

3 个答案:

答案 0 :(得分:30)

我认为您可以通过将表单放在一个部分(我们将其称为simple_form)并将此代码放在reload.js.erb中来简化此操作:

$("#entryform").html("<%= escape_javascript(render :partial => 'simple_form') %>");

我不熟悉jQuery的load方法,但我认为它会发出第二个请求。具有渲染错误的键是您正在使用的实例变量(@brand),而渲染表单必须与您尝试在创建中保存的表单相同,因此您可以检查其上的错误。这就是为什么在想要渲染错误时始终使用render而不是redirect_to的原因。如果您执行重定向,则会启动新请求,这意味着@brand会重新初始化。我假设你的$(...).load(...)遇到了同样的问题。

答案 1 :(得分:1)

感谢所有关于此问题的Q&amp; A.它救了我。

简化@ tsherif的文件结构一个档次(假设你已经有一个js文件),我通过在表单上直接调用render并通过javascript / coffeescript显示来解决这个问题。

#immediate_controller
def action_with_modal
  @brand = params[:failed_brand] || Brand.new
end

#brands_controller
def create
  @brand = Brand.new(params[:brand]) 

  respond_to do |format|
    if @brand.save
      ...
    else
      params[:failed_brand] = @brand
      ...
      format.js { render 'simple_form' }
    end
  end
end

#coffeescript
$('form-selectors-here').on 'ajax:error', @reRegister

reRegister: (e, data) =>
  $("div-that-contains-form").html(data.responseText)

答案 2 :(得分:0)

检查一下:调用.html(...)将复制表单包装器div。 使用.replateWith(...)代替=]