【问题标题】:Display inline errors with simple_form in a Bootstrap Ajax modal在 Bootstrap Ajax 模式中使用 simple_form 显示内联错误
【发布时间】:2012-11-04 16:49:59
【问题描述】:

我发现了类似的 StackOverflow 问题 herehere,但仍然无法正常工作。

我正在使用 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 partial。 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 行,也就是这个 sn-p 中的 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 变量?或者有没有更简单的方法来处理这个问题?

【问题讨论】:

    标签: jquery twitter-bootstrap ruby-on-rails-3.2 simple-form


    【解决方案1】:

    我不明白您为什么需要重置表单。我觉得没必要。

    $(function($) {
      $("#new_contact")
        .bind("ajax:success", function(event, data, status, xhr) {
          ...
        })
    });
    

    您需要修复的一件事是您的 new_model_error.js.erb 中的以下行,否则您将有 id="new-contact-modal" 的重复 div .

    old:
    $("#new-contact-modal").html($(modal)); 
    new:
    $("#new-contact-modal").html($(modal).html());
    

    如果您还有问题,请告诉我。

    【讨论】:

    • 这个想法是在成功时重置表单,这样如果用户想要打开(取消隐藏)它并添加另一个联系人,它将被清除。现在我想起来了,如果以前的表单有错误消息,这可能是个问题——我可能需要从服务器重新加载表单。无论如何,无法使用错误消息呈现表单的问题是不同的——它永远不会执行我的 contacts.js 代码。我会再做一些。您的其他建议并回复。
    • 我承认我对gist 中的$('#signin-modal').html($(modal)); 有点困惑。如果modal是一个包含HTML(我们要注入的部分)的变量字符串,为什么需要将其称为$(modal)?我认为该符号是为了让 JQuery 从 DOM 选择器创建一个包装集。不应该只是$("#new-contact-modal").html(modal);吗?无论如何,我的“JSON.parse:意外字符”错误发生在此之前:它试图加载 app/views/contacts/new_modal_error.js.erb 的内容。
    【解决方案2】:

    这里的主要问题是使用data-type =&gt; :json 调用表单。这意味着它将期望 JSON 响应,但我希望它传回 JavaScript。解决方案是设置data-type =&gt; :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。我最终创建了一个仅包含表单的部分,在 &lt;div id="new-contact-form-wrapper"&gt; 包装器内调用部分,然后以 wrapper 为目标来替换表单:

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

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

    【讨论】:

      猜你喜欢
      • 2019-01-15
      • 2016-04-12
      • 1970-01-01
      • 2018-11-08
      • 2013-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-25
      相关资源
      最近更新 更多