Rails 3:“带字段的错误”包装器改变了页面外观。 如何避免这一点?

电子邮件字段

<label for="job_client_email">Email: </label> <input type="email" name="job[client_email]" id="job_client_email"> 

看起来像这样:

without_error

但是,如果电子邮件validation失败,则会变成:

 <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> 

看起来像这样:

with_error

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

你应该重写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 } 

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

 config.action_view.field_error_proc = Proc.new { |html_tag, instance| html_tag } 

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

你看到的视觉差异正在发生,因为div元素是一个块元素。 将此样式添加到您的CSS文件,使其performance得像一个内联元素:

 .field_with_errors { display: inline; } 

我目前使用这个解决scheme,放在一个初始化程序中:

 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 

这允许我仅仅添加一个类名到适当的标签,而不创build额外的元素。

额外的代码正在被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 } 

或者,您可以将其更改为适合您的用户界面的内容:

 config.action_view.field_error_proc = Proc.new { |html_tag, instance| "<span class='field_with_errors'>#{html_tag}</span>".html_safe } 

除了@phobetron的答案,当你有其他类属性的<label for="..."><i class="icon my-icon"></i>My field</label> ,如<label for="..."><i class="icon my-icon"></i>My field</label>

我对他的解决scheme做了一些改变:

 # config/initializers/field_with_error.rb 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('>') if class_attr_index.nil? || first_tag_end_index > class_attr_index html_tag.insert(class_attr_index + 7, 'error ') else html_tag.insert(first_tag_end_index, ' class="error"') end end 

如果由于某种原因,你仍然在使用Rails 2(像我一样)看看这里的SOpost。

它提供了一个脚本来放入初始化程序。

有一件事要记住(就像我今天发现的那样),如果你浮动标签或input字段(我将所有input字段右移),即使你重写了ActionView :: Base.field_error_proc。

另一种方法是在CSS格式化中放置更深的级别,如下所示:

 .field_with_errors label { padding: 2px; background-color: red; } .field_with_errors input[type="text"] { padding: 3px 2px; border: 2px solid red; } 

我正在使用Rails 5和Materialize-Sass,而且我从Rails的默认行为中得到一些问题来处理失败的字段validation,如下图所示,这是因为额外的div添加到validation失败的input字段。

在这里输入图像描述

与@Phobetron合作回答并修改Hugo Demiglio的答案。 我对这些代码块进行了一些调整,在下列情况下,我可以很好地工作:

  • 如果inputlabel都有自己的class属性
    • <input type="my-field" class="control">
    • <label class="active" for="...">My field</label>
  • 如果inputlabel标签没有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属性中的现有类中(如果存在),或者如果它不存在于标签input标记中,则会创builderror类。

 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 

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

这是我在@ Phobetron的答案上build立的解决scheme。 将这段代码放在application.rb ,由相应的form.error :p调用生成的<p><span>标记将接收fields_with_errors css标记。 其余的将收到error CSS类。

 config.action_view.field_error_proc = Proc.new { |html_tag, instance| class_attr_index = html_tag.index 'class="' if class_attr_index # target only p's and span's with class error already there error_class = if html_tag =~ /^<(p|span).*error/ 'field_with_errors ' else 'error ' end html_tag.insert class_attr_index + 7, error_class else html_tag.insert html_tag.index('>'), ' class="error"' end } 

我发现这种方式是以前所有forms中最灵活和最不起眼的。

如果只是为了造型的目的(你不介意的div ),你可以添加到你的CSS:

 div.field_with_errors { display: inline; } 

div会像span ,不会干扰你的devise(因为div是一个块元素 – display: block; – 默认情况下,它会在closures后产生一个新行; spaninline ,所以不会)。

我做了一个选项来禁用一些对象的这个可怕的事情

 # config/initializers/field_error_proc.rb module ActiveModel::Conversion attr_accessor :skip_field_error_wrapper end ActionView::Base.field_error_proc = Proc.new {|html_tag, instance| if instance.object && instance.object.skip_field_error_wrapper html_tag.html_safe else "<div class=\"field_with_errors\">#{html_tag}</div>".html_safe end } 

所以可以这样使用它:

 @user.skip_field_error_wrapper = true form_for(@user) do |f| ... end 

如果只涉及样式问题,我们可以覆盖“field_with_errors”。 但是,因为这可能会影响我们的应用程序中的其他forms,所以最好只用这种forms覆盖“field_with_errors”类。

考虑到“parent_class”是表单错误字段的父类之一(表单的类或任何错误字段的父元素的类),那么

  .parent_class .field_with_errors { display: inline; } 

它将解决这个问题,也不会干扰我们应用程序中的任何其他forms。

要么

如果我们需要重写整个应用程序的“field_with_errors”风格,那么@dontangg说,

 .field_with_errors { display: inline; } 

将做解决。 希望它有助于:)

Interesting Posts