Skip to main content
 首页 » 编程设计

jquery之在 Bootstrap Ajax 模式中使用 simple_form 显示内联错误

2026年07月24日11dudu

我发现了类似的 StackOverflow 问题 here和 here但仍然无法让它发挥作用。

我正在使用 Rails 3.2.8、SimpleForm 2.0.4 和 Twitter Bootstrap 2.1.1(通过 bootstrap-sass gem 2.1.1.0)。

用户应该能够从模式弹出窗口添加联系人。如果存在验证错误,它们应该内联显示,就像用户使用表单的非模式版本一样(字段周围有红色边框,字段旁边有错误消息)。

我像这样加载模式:

<a data-toggle="modal" data-target="#new-contact-modal">Go modal!</a> 

这是 Bootstrap 模式,它调用非模式版本中使用的相同 contacts/contact_fields 部分。 app/views/contacts/_new_modal.html.erb:

<div id="new-contact-modal" class="modal hide fade" tabindex="-1"  
     role="dialog" aria-labelledby="new-contact-modal-label"  
     aria-hidden="true"> 
  <div class="modal-header"> 
    <button type="button" class="close" data-dismiss="modal"  
     aria-hidden="true">×</button> 
    <h3 id="new-contact-modal-label"><%= t("contacts.new.header") %></h3> 
  </div> 
  <%= simple_form_for(@contact,  
      :remote => true, 
      :html => {:class => "form-horizontal",  
                "data-type" => :json }) do |contact_form| %> 
    <div id="new-contact-body" class="modal-body"> 
      <%= render 'contacts/contact_fields', :f => contact_form %> 
    </div> 
    <div class="modal-footer"> 
      <%= contact_form.submit :class => "btn btn-primary",  
          :"data-loading-text"=> ('simple_form.creating') %> 
      <%= t('simple_form.buttons.or') %> 
      <a data-dismiss="modal" aria-hidden="true"> 
        <%= t('simple_form.buttons.cancel') %> 
      </a> 
    </div> 
  <% end %> 
</div> 

app/controllers/contacts_controller.rb(故意注释掉 format.json 行,因为我尝试使用 JavaScript 发回整个模式):

def create 
  @contact = Contact.new(params[:contact]) 
  <...some additional processing...> 
  respond_to do |format| 
    if @contact.save 
      format.html { flash[:success] = "Contact added." 
                    redirect_to @contact } 
      format.json { render json: @contact, status: :created, location: @contact} 
    else 
      format.html { render action: "new" } 
      #format.json { render json: @contact.errors, status: :unprocessable_entity } 
      format.js { render 'new_modal_error' } 
    end 

app/views/contacts/new_modal_error.js.erb

var modal = "<%= escape_javascript(render :partial => 'contacts/new_modal', :locals => { :contact => @contact.errors }) %>"; 
$("#new-contact-modal").html($(modal)); 

app/assets/javascripts/contacts.js 一些 JQuery 用于重置表单并在成功时关闭模式。

$(function($) { 
  $("#new_contact") 
    .bind("ajax:success", function(event, data, status, xhr) { 
      // http://simple.procoding.net/2008/11/22/how-to-reset-form-with-jquery : 
      $(this).each(function(){ 
        this.reset(); 
      });        
      $("#new-contact-modal").modal("hide"); 
    }) 
}); 

好消息是,当表单没有错误时,这会起作用:添加联系人并隐藏模式。但是,如果存在验证错误,我会收到消息“JSON.parse:意外字符”。这来自 jquery.js,第 515 行,这是此代码段中的 return 语句:

// Attempt to parse using the native JSON parser first 
if ( window.JSON && window.JSON.parse ) { 
    return window.JSON.parse( data ); 
} 

如果我检查 data,我会发现这是我的 new_modal_error.js 文件的内容,完全用表单错误展开,并转义为 JavaScript。但它不是 JSON。

我错过了什么?如何让页面将 new_modal_error.js 作为 JavaScript 文件而不是 JSON 变量进行处理?或者有更简单的方法来处理这个问题吗?

请您参考如下方法:

这里的主要问题是使用 data-type => :json 调用表单。 。这意味着它需要一个 JSON 响应,但我希望它传回 JavaScript。解决办法是设置data-type => :script (或者直接将其保留,让 Rails 推断 JavaScript):

:html => {:class => "form-horizontal",  
          "data-type" => :script }) do |contact_form| %> 

感谢本文解释了各种数据类型,并澄清了数据类型指的是响应,而不是数据的提交:

Rails 3 Remote Links and Forms Part 2: Data-type (with jQuery)

“jQuery 的 .ajax() 方法提供了一个名为 dataType 的可选参数来指定所需的响应数据类型。”

我认为 @wanghq 指出的另一个问题是 JQuery 的 .html()方法更新对象的innerHTML。我最终创建了一个仅包含表单的部分,并将该部分称为 <div id="new-contact-form-wrapper">包装器,然后定位包装器来替换表单:

var myForm = "<%= escape_javascript(render :partial => 'contacts/new_modal_form', :locals => { :contact => @contact.errors }) %>"; 
$("#new-contact-form-wrapper").html(myForm); 

我仍在努力传递变量、成功时清除表单等。由于我使用的是 Controller 中的部分内容,我可能会继续放置所有 JQuery(对于成功和失败)在那里,所以我不需要 app/assets/javascripts/contacts.js。