Rails 3:"field-with-errors"包装器改变了页面外观.怎么避免这个?

Mis*_*hko 129 validation ruby-on-rails ruby-on-rails-3 field-with-errors

电邮领域:

<label for="job_client_email">Email: </label> 
<input type="email" name="job[client_email]" id="job_client_email">
Run Code Online (Sandbox Code Playgroud)

看起来像这样:

without_error

但是,如果电子邮件验证失败,它将变为:

<div class="field_with_errors">
  <label for="job_client_email">Email: </label>
</div> 
<div class="field_with_errors">
  <input type="email" value="wrong email" name="job[client_email]" id="job_client_email">
</div>
Run Code Online (Sandbox Code Playgroud)

看起来像这样:

with_error

我怎么能避免这种外观变化?

Rya*_*igg 230

你应该覆盖ActionView::Base.field_error_proc.它目前定义为ActionView::Base:

 @@field_error_proc = Proc.new{ |html_tag, instance| 
   "<div class=\"field_with_errors\">#{html_tag}</div>".html_safe
 }
Run Code Online (Sandbox Code Playgroud)

您可以通过将其放在应用程序的类中来覆盖它config/application.rb:

config.action_view.field_error_proc = Proc.new { |html_tag, instance| 
  html_tag
}
Run Code Online (Sandbox Code Playgroud)

重新启动rails服务器以使此更改生效.

  • 一个小问题:为什么`label`和`input`都被包裹了?Rails如何决定包装什么? (4认同)
  • 这可能是为了您可以设置带有错误的字段标签的样式.此外,rails知道要包装的内容,因为你告诉它哪些字段属于你正在制作表单的资源的属性:`f.label:password`和`@ resource.errors`中的`f.password_field:password`会有一个`[:密码]`错误集. (4认同)
  • 如果你正在使用twitter bootstrap,或者你想在field_error_proc中做一些你可以做的事情的例子,请知道这个令人敬畏的要点:https://gist.github.com/1464315 (3认同)
  • Anurag:如果html_tag碰巧是nil,或者是字符串以外的任何东西,那么普通的html_tag.html_safe就会出错.把它放在"#{html_tag}"中会隐式调用html_tag.to_s,希望它会返回一个字符串,然后它就能响应html_safe (3认同)
  • 为什么要做"#{html_tag}".html_safe,而不是html_tag.html_safe? (2认同)

don*_*ngg 100

您看到的视觉差异正在发生,因为div元素是一个块元素.将此样式添加到CSS文件中,使其行为类似于内联元素:

.field_with_errors { display: inline; }
Run Code Online (Sandbox Code Playgroud)

  • 这是一个hack,因为它否定了`html_tag`上使用的`display:`属性(和其他布局样式). (2认同)
  • 我不认为这是一种黑客行为。添加此 css 之前使用的“display”属性是“block”,这会导致不希望的视觉差异。它不会否定标签上的任何其他布局样式。然而,如果您想更改/删除包含错误字段的标签,Ryan Bigg 的答案是完美的。 (2认同)

小智 72

我目前使用此解决方案,放在初始化程序中:

ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
  class_attr_index = html_tag.index 'class="'

  if class_attr_index
    html_tag.insert class_attr_index+7, 'error '
  else
    html_tag.insert html_tag.index('>'), ' class="error"'
  end
end
Run Code Online (Sandbox Code Playgroud)

这允许我只是将类名添加到适当的标记,而不创建其他元素.

  • 这对于以不引人注目的方式使用错误字段非常棒. (2认同)

Dan*_*ail 20

额外的代码正在添加ActionView::Base.field_error_proc.如果您不是field_with_errors用来设置表单样式,可以在application.rb以下位置覆盖它:

config.action_view.field_error_proc = Proc.new { |html_tag, instance| html_tag.html_safe }
Run Code Online (Sandbox Code Playgroud)

或者,您可以将其更改为适合您的UI:

config.action_view.field_error_proc = Proc.new { |html_tag, instance| "<span class='field_with_errors'>#{html_tag}</span>".html_safe }
Run Code Online (Sandbox Code Playgroud)


ale*_*aio 5

我正在使用 Rails 5 和Materialize-Sass,我在 Rails 处理失败字段验证的默认行为方面遇到了一些问题,如下图所示,这是因为div在验证失败的输入字段中添加了额外的内容。

在此处输入图片说明

使用@Phobetron 回答并修改 Hugo Demiglio 的回答。我对这些代码块进行了一些调整,并且在以下情况下运行良好:

  • 如果两者inputlabelclass任何地方都有自己的属性
    • <input type="my-field" class="control">
    • <label class="active" for="...">My field</label>
  • 如果inputorlabel标签没有class属性
    • <input type="my-field">
    • <label for="...">My field</label>
  • 如果label标签内部有另一个标签class attribute
    • <label for="..."><i class="icon-name"></i>My field</label>

在所有这些情况下,如果存在,error类将被添加到class属性中的现有类,或者如果它不存在于标签输入标签中,则将创建它。

ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
    class_attr_index = html_tag.index('class="')
    first_tag_end_index = html_tag.index('>')

    # Just to inspect variables in the console
    puts ' ' * 50
    pp(html_tag)
    pp(class_attr_index)
    pp(first_tag_end_index)

    if class_attr_index.nil? || class_attr_index > first_tag_end_index
        html_tag.insert(first_tag_end_index, ' class="error"')
    else
        html_tag.insert(class_attr_index + 7, 'error ')
    end

    # Just to see resulting tag in the console
    pp(html_tag)
end
Run Code Online (Sandbox Code Playgroud)

我希望它对像我一样条件相同的人有用。