当Twitter Bootstrap模态窗口包含Rails表单助手时,如何显示错误信息

3
我想询问如何在Rails表单帮助程序中使用Twitter Bootstrap模态窗口,并显示表单验证错误消息。我正在使用Rails 3.2和Twitter Bootstrap 2.0。
我在Twitter Bootstrap模态窗口中放置了一个表单。页面上有一个按钮,用于打开模态窗口并显示表单。一切都很好,但是当表单提交时出现错误,由于表单位于(最初未显示的)模态窗口内,因此无法看到错误消息。
我需要使用jQuery来测试表单是否包含Rails错误消息,并在渲染页面时覆盖“display:none;”样式(或切换模态窗口以显示)。
我尝试将以下代码添加到我的assets/javascripts/application.js文件中,但它不起作用:
$('document').ready(function() {
  if ($('#error_explanation').length > 0) {
    $("#request_invite").css("display", "block");
  }
})

而且:
$('document').ready(function() {
  if ($('#error_explanation').length > 0) {
    $("#request_invite").modal('toggle');
  }
})

如何在出现错误消息时显示模态窗口或切换打开它?

这是显示Twitter Bootstrap模态窗口中表单的代码(Haml):

#request-invite.modal{:style => "display: none;"}
  = form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f|
    .modal-header
      %a.close{"data-dismiss" => "modal"} ×
      %h3 Request Invitation
    .modal-body
      - if @user.errors.any?
        #error_explanation
          %ul
            - @user.errors.full_messages.each do |msg|
              %li= msg
      %p
        = f.label :email
        %br/
        = f.email_field :email
    .modal-footer
      = f.submit "Request Invitation", :class => "btn.btn-success"
      %a.btn{"data-dismiss" => "modal", :href => "#"} Close
#romance-copy{:style => "text-align: center; margin-top: 100px"}
  %h2 Want in?
#call-to-action{:style => "text-align: center; margin-top: 100px"}
  %a.btn.btn-primary.btn-large{"data-toggle" => "modal", :href => "#request-invite"} Request invite

有可能弹出框不会在文档准备好时加载。可能它正在文档准备好() 时加载。为了调试目的,请尝试在弹出窗口内执行JavaScript代码。 - Sairam
Kenrick Chien 指出了一个笔误:request_invite != request-invite。两个代码片段都可以工作。带有 "modal('toggle')" 的片段是最佳的,因为当触发模态时,模态具有覆盖页面的深色背景。仅使用 "display: block" 可以显示模态,但不会应用深色背景。 - Daniel Kehoe
5个回答

3

看起来是打错了?你在 Haml 中的 div 有一个 ID 是 request-invite(带有破折号)。 然而,你的 jQuery 正在寻找一个带有下划线的 ID。


2

正如@wanghq所说(部分内容由@miked提供),我认为最好的方法是使用AJAX在模态框中呈现HTML并提交表单数据。这样,所有逻辑都委托给服务器端,在视图中仅使用JS进行效果,保持视图干净(没有助手或逻辑涉及)。

使用此解决方案时,当客户端上的JS不起作用时,您可以通过使用相同的控制器操作来优雅地降级以呈现表单。一个简单的例子:

def new
  @user = User.new
  # some stuff...
  render :handler => 'haml', :layout => !request.xhr?
end

# similar logic should be used for #create action

对于 (d)html 部分,您可以使用 Ruby 来检测是否由于错误而显示。我的意思是像这样的东西(如果需要,您可以编写帮助程序):

#request-invite.modal{:style => "display: #{ @user.errors.any? ? 'block' : 'none' };"}

作为一个注记,使用simple_form 2.0.x,你将获得twitter-bootstrap标记的支持(我的意思是,它会为你的表单生成bootstrap友好的标记)。这样,你可以在模板中DRY一些逻辑(例如: 检查@user.errors来显示错误消息)。
这样,你不需要使用JS进行检查 ;)
以上为我的两分钱;-)

2
我想提供另一个选项。你所使用的方法应该能够正常工作,但为什么不使用AJAX在出现错误时显示错误消息呢?响应JS的作用是添加额外的样式来显示错误消息。

我需要使用jQuery来测试表单是否包含Rails错误消息,并在页面呈现时覆盖"display: none;"样式(或切换模态窗口以显示)。

请看http://www.twitmark.me/。尝试使用Twitter登录。输入一个虚假的邀请码,看看错误信息是什么样子。这是一个更好的解决方案吗?

Twitmark.me 的验证看起来正是我想要的。您是否重新加载弹出窗口的内容,以便将外部的<div>标记为“error”类,并添加“inline-help”对象?您如何触发重新加载--从JQuery吗?控制器在失败时会做什么?我觉得我已经拥有大部分的组件,但是无法将它们缝合在一起。 - Mark Berry
你的控制器动作只需要响应.js请求即可。 - wanghq
你的控制器操作只需要用js响应ajax请求即可。视图代码如https://gist.github.com/4070421。 - wanghq
非常感谢。我会尝试一下。这很令人困惑,因为默认的控制器代码包含了类似于以下的失败处理:format.json { render json: @invitation.error, status: :unprocessable_entity }。但是我也看到过一个例子,它既有JSON响应,又添加了类似于以下的内容:format.js {render 'create' }。但是看起来你的代码根本不需要format_json,对吗? - Mark Berry
它们很相似。我更喜欢返回js而不是json,因为我不想编写大量的js代码来将错误样式添加到表单中。正如您可以从我的链接中看到的那样,使用@invitation呈现表单会添加错误样式,唯一需要做的就是将html添加到页面中。 - wanghq
再次感谢。我仍然卡住了,所以我发布了一个新问题:在Bootstrap Ajax模态框中使用simple_form显示内联错误 - Mark Berry

1
我可能误解了问题,但从我所看到的来看,当模态加载时,您的error_explanation div没有被隐藏(display:none),因为它是在if @user.errors.any?块中进行条件判断的。因此,无论您使用什么javascript,它都不会起作用,因为它不存在。
首先,尝试:
.modal-body
  #error_explanation
    - if @user.errors.any?
      %ul
        - @user.errors.full_messages.each do |msg|
          %li= msg

这样,div 将存在,只有在需要显示错误时,ul 才会显示项目。


1

为什么需要jQuery?为什么不直接使用已有的条件语句呢?

这段代码很糟糕,你可能可以将其优化(移动到helper或其他地方),但你应该能够理解它的意思。

- def display?; @user.errors.any? ? "block;" : "none;"; end;
#request-invite.modal{:style => "display: " + display? }

优秀的建议。但是使用jQuery切换模态框有一个优点。模态框具有覆盖整个页面的黑色背景,当触发模态框时该背景会出现。只使用"display:block"可以显示模态框,但不会应用黑色背景。 - Daniel Kehoe
顺便提一下,正确的代码应该有括号:#request-invite.modal{:style => "display: " + (@user.errors.any? ? "block;" : "none;") } - Daniel Kehoe
我将它移入一个方法中,以使代码更加简洁。我从不使用Twitter模态框,因为它们很糟糕(就JavaScript而言)。在我的当前应用程序中,我使用一个模板和自定义的JavaScript对象来根据点击的内容隐藏、显示和转换。这比Bootstrap模态框插件要少得多的JavaScript代码行数。从长远来看,这是一个更加灵活的解决方案。所有背景和模态框的样式都在CSS中。$('<div class="modal-backdrop"/>').appendTo(document.body) - mwoods79

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接