Rails “field-with-errors” 获取父节点

Rails “field-with-errors” get parent node

我有这样的火腿

= form_for [:admin, @school] do |f|
  [...]
  = f.fields_for :address do |a|
    [...]
    .col-md-3
      .form-group.form-md-line-input.form-md-floating-label
        = a.text_field :postal_code, id: 'form_3', class: 'form-control'
        %label{:for => "form_3"} Postleitzahl

呈现给

<div class="col-md-3">
  <div class="form-group form-md-line-input form-md-floating-label">
    <input id="form_3" class="form-control" type="text" value="" name="school[address_attributes][postal_code]">
    <label for="form_3">Postleitzahl</label>
  </div>
</div>

出现错误时,代码应该是这样的

[...]
<div class="form-group form-md-line-input form-md-floating-label has-error">
[...]

要解决这个问题: 有没有办法 select config/initializers/field_error_proc.rb 中的父节点?

ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|

--> Nokogiri::HTML::DocumentFragment.parse(html_tag).parent returns nil.

好的,所以,我现在要忘记记忆了,但这应该会有所帮助。

ActionView::Base.field_error_proc 太糟糕了。不要使用它。我这样说是因为对于不明白它应该做什么的人来说,这是极其不可预测的(例如,如果你不知道它是什么,你就不会明白为什么这些 div 突然出现在你的领域周围,并弄乱你的造型)。另外,这不是你需要的。

所以,这就是你要做的。由于您使用的是 HAML/Slim,因此您无法有条件地添加单个 class。因此,您必须将整个内容封装在一个 if 语句中,这很好。您可以使用 #errors:

检查错误
.col-md-3
  - if @school.errors[:postal_code].any?
    .form-group.form-md-line-input.form-md-floating-label.has-error
      - # ...
   - else
    .form-group.form-md-line-input.form-md-floating-label
       - # ...

@school.errors[:postal_code].any? 检查是否存在与 :postal_code 字段关联的任何验证错误。如果有,它 returns 为真,因此我们创建一个 div 并使用适当的 class 作为响应。

希望对您有所帮助!

如果要

的父节点
<div class="form-group form-md-line-input form-md-floating-label has-error">

尝试:

require 'nokogiri'

doc = Nokogiri::HTML::DocumentFragment.parse(<<EOT)
<div class="col-md-3">
  <div class="form-group form-md-line-input form-md-floating-label">
    <input id="form_3" class="form-control" type="text" value="" name="school[address_attributes][postal_code]">
    <label for="form_3">Postleitzahl</label>
  </div>
</div>
EOT

div = doc.at('[class="form-group form-md-line-input form-md-floating-label"]') 
# => #<Nokogiri::XML::Element:0x3ff0e0c14d80 name="div" attributes=[#<Nokogiri::XML::Attr:0x3ff0e0c14ac4 name="class" value="form-group form-md-line-input form-md-floating-label">] children=[#<Nokogiri::XML::Text:0x3ff0e0c141dc "\n    ">, #<Nokogiri::XML::Element:0x3ff0e0c14060 name="input" attributes=[#<Nokogiri::XML::Attr:0x3ff0e0c1422c name="id" value="form_3">, #<Nokogiri::XML::Attr:0x3ff0e0c14560 name="class" value="form-control">, #<Nokogiri::XML::Attr:0x3ff0e0c14740 name="type" value="text">, #<Nokogiri::XML::Attr:0x3ff0e0c147b8 name="value">, #<Nokogiri::XML::Attr:0x3ff0e0c148d0 name="name" value="school[address_attributes][postal_code]">]>, #<Nokogiri::XML::Text:0x3ff0e0c054e8 "\n    ">, #<Nokogiri::XML::Element:0x3ff0e0c053d0 name="label" attributes=[#<Nokogiri::XML::Attr:0x3ff0e0c052f4 name="for" value="form_3">] children=[#<Nokogiri::XML::Text:0x3ff0e0c04b74 "Postleitzahl">]>, #<Nokogiri::XML::Text:0x3ff0e0c0487c "\n  ">]>

div.parent.to_html 
# => "<div class=\"col-md-3\">\n  <div class=\"form-group form-md-line-input form-md-floating-label\">\n    <input id=\"form_3\" class=\"form-control\" type=\"text\" value=\"\" name=\"school[address_attributes][postal_code]\">\n    <label for=\"form_3\">Postleitzahl</label>\n  </div>\n</div>"

通常,如果我们知道我们想要一个特定的 class,我们可以使用 shorthand 来定位使用它的节点:

doc.at('.form-group') 
# => #(Element:0x3fec6acbc8d4 {
#      name = "div",
#      attributes = [
#        #(Attr:0x3fec6acbc0dc {
#          name = "class",
#          value = "form-group form-md-line-input form-md-floating-label"
#          })],
#      children = [
#        #(Text "\n    "),
#        #(Element:0x3fec6aca83ac {
#          name = "input",
#          attributes = [
#            #(Attr:0x3fec6accdea4 { name = "id", value = "form_3" }),
#            #(Attr:0x3fec6accde90 { name = "class", value = "form-control" }),
#            #(Attr:0x3fec6accde7c { name = "type", value = "text" }),
#            #(Attr:0x3fec6accde54 { name = "value", value = "" }),
#            #(Attr:0x3fec6accde2c {
#              name = "name",
#              value = "school[address_attributes][postal_code]"
#              })]
#          }),
#        #(Text "\n    "),
#        #(Element:0x3fec6acdce04 {
#          name = "label",
#          attributes = [
#            #(Attr:0x3fec6acdc9cc { name = "for", value = "form_3" })],
#          children = [ #(Text "Postleitzahl")]
#          }),
#        #(Text "\n  ")]
#      })

当我们想要使用多个 classes 时,这会崩溃:

doc.at('.form-group form-md-line-input') 
# => nil

但是我上面使用 [class="..."] 的形式可以工作。