Rails 3:“带字段的错误”包装器改变了页面外观。 如何避免这一点?
电子邮件字段
<label for="job_client_email">Email: </label> <input type="email" name="job[client_email]" id="job_client_email">
看起来像这样:
但是,如果电子邮件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>
看起来像这样:
我怎样才能避免这种外观变化?
你应该重写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的答案。 我对这些代码块进行了一些调整,在下列情况下,我可以很好地工作:
- 如果
input
和label
都有自己的class
属性-
<input type="my-field" class="control">
-
<label class="active" for="...">My field</label>
-
- 如果
input
或label
标签没有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后产生一个新行; span
是inline
,所以不会)。
我做了一个选项来禁用一些对象的这个可怕的事情
# 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; }
将做解决。 希望它有助于:)