Ruby-on-rails Rails 3:“field-with-errors”包装器改变了页面外观。如何避免这种情况?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5267998/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rails 3: "field-with-errors" wrapper changes the page appearance. How to avoid this?
提问by Misha Moroshko
Email field:
电子邮件字段:
<label for="job_client_email">Email: </label>
<input type="email" name="job[client_email]" id="job_client_email">
looks like this:
看起来像这样:


But, if the email validation fails, it becomes:
但是,如果电子邮件验证失败,则变为:
<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>
which looks like this:
看起来像这样:


How could I avoid this appearance change ?
我怎样才能避免这种外观变化?
回答by Ryan Bigg
You should override ActionView::Base.field_error_proc. It's currently defined as this within ActionView::Base:
你应该覆盖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
}
You can override it by putting this in your application's class inside config/application.rb:
您可以通过将其放在应用程序的类中来覆盖它config/application.rb:
config.action_view.field_error_proc = Proc.new { |html_tag, instance|
html_tag
}
Restart rails server for this change to take effect.
重新启动 rails 服务器以使此更改生效。
回答by dontangg
The visual difference you are seeing is happening because the divelement is a block element. Add this style to your CSS file to make it behave like an inline element:
您看到的视觉差异正在发生,因为该div元素是块元素。将此样式添加到您的 CSS 文件中,使其表现得像一个内联元素:
.field_with_errors { display: inline; }
回答by Phobetron
I currently use this solution, placed in an initializer:
我目前使用这个解决方案,放在一个初始化程序中:
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
This allows me to merely add a class name to the appropriate tag, without creating additional elements.
这允许我仅将类名添加到适当的标记,而无需创建其他元素。
回答by Dan Cheail
The extra code is being added by ActionView::Base.field_error_proc. If you're not using field_with_errorsto style your form, you can override it in application.rb:
额外的代码是由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 }
Alternatively, you can change it to something that suits your UI:
或者,您可以将其更改为适合您的 UI 的内容:
config.action_view.field_error_proc = Proc.new { |html_tag, instance| "<span class='field_with_errors'>#{html_tag}</span>".html_safe }
回答by alexventuraio
I am working with Rails 5 and Materialize-Sassand I am getting some issues with the default behavior from Rails to treat failed field validations as in the image below and it was because of the extra divadded to the input fields where validation failed.
我正在使用 Rails 5 和Materialize-Sass,我在 Rails 处理失败字段验证的默认行为方面遇到了一些问题,如下图所示,这是因为div在验证失败的输入字段中添加了额外的内容。
Working with @Phobetron answer and modifying Hugo Demiglio's answer too. I made some adjustments to those blocks of code and I get something working well in the following cases:
使用@Phobetron 回答并修改 Hugo Demiglio 的回答。我对这些代码块进行了一些调整,并且在以下情况下运行良好:
- If both
inputandlabelhas their ownclassattribute anywhere<input type="my-field" class="control"><label class="active" for="...">My field</label>
- If the
inputorlabeltags does not have aclassattribute<input type="my-field"><label for="...">My field</label>
- if the
labeltag has another tag inside with theclass attribute<label for="..."><i class="icon-name"></i>My field</label>
- 如果两者
input和label在class任何地方都有自己的属性<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>
In all those cases the errorclass will be added to the existing classes in the classattribute if exist or it will be created if it is not present in the labelor inputtags.
在所有这些情况下,如果存在,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
I hope it could be useful for someone with the same conditions like me.
我希望它对像我一样条件相同的人有用。
回答by Hugo Demiglio
In addition of @phobetron answer, which doesn't work when you have other tag with class attribute, like <label for="..."><i class="icon my-icon"></i>My field</label>.
除了@phobetron 答案之外,当您有其他具有 class 属性的标签(如<label for="..."><i class="icon my-icon"></i>My field</label>.
I did some changes on his solution:
我对他的解决方案做了一些改变:
# 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
回答by Pavel Evstigneev
I made an option to disable this terrible thing for some objects
我做了一个选项来禁用某些对象的这个可怕的东西
# 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
}
So can use it like this:
所以可以像这样使用它:
@user.skip_field_error_wrapper = true
form_for(@user) do |f|
...
end
回答by ScottJShea
回答by Kevin Reeth
One thing to keep in mind (as I discovered working through this today) is that if you float either the label or input fields (I'm floating all of the input fields right), the css will break even if you override ActionView::Base.field_error_proc.
要记住的一件事(正如我今天发现的那样)是,如果您浮动标签或输入字段(我将所有输入字段向右浮动),即使您覆盖 ActionView,css 也会中断: Base.field_error_proc。
An alternative is to drop a level deeper in the CSS formatting like so:
另一种方法是在 CSS 格式中降低一个更深的级别,如下所示:
.field_with_errors label {
padding: 2px;
background-color: red;
}
.field_with_errors input[type="text"] {
padding: 3px 2px;
border: 2px solid red;
}
回答by dgilperez
This is my solution building on top of @Phobetron's answer. Placing this code in application.rb, your <p>and <span>tags generated by the corresponding form.error :pcalls will receive the fields_with_errorscss tag. The rest will receive the errorCSS class.
这是我建立在@Phobetron 答案之上的解决方案。将此代码放在 中application.rb,相应调用生成的<p>和<span>标签form.error :p将收到fields_with_errorscss 标签。其余的将接收errorCSS 类。
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
}
I found this way the most flexible and unobstrusive of all previous to style the response across my forms.
我发现这种方式是以前最灵活和最不引人注目的方式,可以在我的表单中设置响应样式。

![Ruby-on-rails 如何从 params[:something] 中删除一个字段](/res/img/loading.gif)