Rails - ActionView :: Base.field_error_proc向上移动DOM树? [英] Rails - ActionView::Base.field_error_proc moving up the DOM tree?

查看:163
本文介绍了Rails - ActionView :: Base.field_error_proc向上移动DOM树?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有从传入的html_tag元素上去DOM树?

Is there anyway to go up the DOM tree from the html_tag element passed in?

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

有没有办法我可以实现这个方法来移动DOM树,并在父div上放置一个类?

Is there anyway I can implement this method to move up the DOM tree and place a class on the parent div?

例如:

<div class="email">
  <label for="user_email">Email Address</label>
  <input id="user_email" name="user[email]" size="30" type="text" value="">
</div>

我想在div.email上放置一个类,而不是直接在输入/标签。

I would like to place a class on the div.email rather than place something directly on the input/label.

这可以用field_error_proc方法完成还是有一个干净的选择?

Can this be done with the field_error_proc method or is there a clean alternative?

我想避免在我对每个表单域的视图中明确地这样做。 (如下)

I want to avoid doing this explicitly in my views on every form field. (like the following)

.email{:class => object.errors[:email].present? 'foo' : nil}
  =form.label :email
  =form.text_field :email

FYI:我的问题的简短答案是在field_error_proc方法中无法访问DOM的其他部分。这是因为这些方法实际上并不构建一个DOM,而是将一串字符串连接在一起。有关一些可能的工作的信息,请阅读以下解决方案。

FYI: Short answer to my question is that there is no way to gain access to additional portions of the DOM in the field_error_proc method. This is due to the fact that these methods are not actually building a DOM but instead just concatting a bunch of strings together. For info on some possible work arounds, read the solutions below.

推荐答案

您有两个选项,我可以想到的顶部我的头:

You have two options that I can think of off the top of my head:

重写ActionView :: Base.field_error_proc

在一个情况我重写了ActionView :: Base.field_error_proc(有一个轨道投掷)。使用一个nokogiri,我更改了proc,以将错误消息添加到input / textarea元素的data-error属性,而不是将它们包装在一个错误div中。然后用jquery写了一些javascript,将所有的输入和他们的标签包装在文件上。如果有与输入/ textarea相关联的错误信息,它将被转移到包装器div。

In one situation I rewrote ActionView::Base.field_error_proc (there is a rails cast on it). Using a little nokogiri, I changed the proc to add the error messages to the input/textarea element's data-error attribute instead of wrapping them in an error div. Then a wrote a little javascript using jquery to wrap all inputs and their labels on document ready. If there was error information associated with the input/textarea, it is transferred to the wrapper div.

我知道这个解决方案依赖于javascript,并且可能有也可能没有优雅的回落,但它在我的情况下工作正常,因为它是一个网络应用程序,而不是一个可访问的网站。我觉得在这种情况下需要javascript。

I know this solution relies on javascript, and may or may not have a graceful fall back, but it works fine in my situation since it is for a web app rather than a publicly accessible site. I feel okay requiring javascript in that scenario.

# place me inside your base controller class
ActionView::Base.field_error_proc = Proc.new do |html_tag, object|
  html = Nokogiri::HTML::DocumentFragment.parse(html_tag)
  html = html.at_css("input") || html.at_css("textarea")
  unless html.nil?
    css_class = html['class'] || "" 
    html['class'] = css_class.split.push("error").join(' ')
    html['data-error'] = object.error_message.join(". ")
    html_tag = html.to_s.html_safe
  end
  html_tag
end

编写自己的ActionView :: Helpers :: FormBuilder

您也可以获得或多或少的相同效果覆盖text_field方法,以便它始终返回一个包装的输入。然后,使用对象变量,访问错误哈希,并将任何所需的错误信息添加到包装器中。这个不需要javascript并且很好地工作,但最终我更喜欢第一种方法,因为我发现它更灵活。但是,如果我正在公开访问的网站,我会使用这种方法。

You can also get more or less the same effect by overriding the text_field method so that it always returns a wrapped input. Then, using the object variable, access the errors hash and add any needed error information to the wrapper. This one does not require javascript and works nicely, but in the end I prefer the first approach because I find it more flexible. If however, I was working on a publicly accessible site, I would use this approach instead.

另外,FYI,我发现可以覆盖check_box和radio_button方法他们总是返回带有关联标签的输入。有很多有趣的事情,你可以做一个自定义的FormBuilder。

Also, FYI, I found it handy to override the check_box and radio_button methods so they always return the input with its associated label. There are lots of fun things you can do with a custom FormBuilder.

# place me inside your projects lib folder
class PrettyFormBuilder < ActionView::Helpers::FormBuilder  
  def check_box(field, label_text, options = {})
    checkbox = super(field, options)
    checkbox += label(field, label_text)
    @template.content_tag(:div, checkbox, :class => "wrapper")
  end
end

上面的例子展示了如何包装一个check_box,但它与text_field大致相同。像我说的一样,如果需要,使用 object.errors 访问错误哈希。这只是冰堡的一小窍门...有一吨你可以使用自定义FormBuilders。

The above example shows how to wrap a check_box, but it is more or less the same with the text_field. Like I said, use the object.errors to access the errors hash if needed. This is just the tip of the ice berg... there is a ton you can do with custom FormBuilders.

如果你去自定义窗体构建器路线,你可能会发现有助于修改以上ActionView :: Base.field_error_proc,因此当有错误时,您不会得到双重包装的字段。

If you go the custom form builder route, you may find it helpful to modify the above ActionView::Base.field_error_proc as follows so you don't get double wrapped fields when there are errors.

ActionView::Base.field_error_proc = Proc.new do |html_tag, object|
  html_tag # return the html tag unmodified and unwrapped
end

要使用表单构建器在form_for方法调用中指定它,或者将以下内容放在应用程序帮助器中:

To use the form builder either specify it in the form_for method call or place the following in your application helper:

# application helper
module ApplicationHelper
  ActionView::Base.default_form_builder = PrettyFormBuilder
end

通常我的解决方案最终使用每种组合来实现所需的结果。

Often my solutions end up using some combination of each to achieve the desired result.

这篇关于Rails - ActionView :: Base.field_error_proc向上移动DOM树?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆