And*_*bbs 8 ruby parsing dom ruby-on-rails actionview
无论如何从传入的html_tag元素上升DOM树?
ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
# implementation
end
Run Code Online (Sandbox Code Playgroud)
无论如何我可以实现这个方法来提升DOM树并在父div上放置一个类吗?
例如:
<div class="email">
<label for="user_email">Email Address</label>
<input id="user_email" name="user[email]" size="30" type="text" value="">
</div>
Run Code Online (Sandbox Code Playgroud)
我想在div.email上放一个类,而不是直接在输入/标签上放置一些东西.
这可以使用field_error_proc方法完成还是有一个干净的替代方案?
我想避免在我对每个表单字段的视图中明确地这样做.(如下)
.email{:class => object.errors[:email].present? 'foo' : nil}
=form.label :email
=form.text_field :email
Run Code Online (Sandbox Code Playgroud)
仅供参考:对我的问题的简短回答是,无法在field_error_proc方法中访问DOM的其他部分.这是因为这些方法实际上并没有构建DOM,而只是将一堆字符串连接在一起.有关可能的解决方法的信息,请阅读以下解决方案.
bre*_*ish 15
你有两个我可以想到的选择:
重写ActionView :: Base.field_error_proc
在一种情况下,我重写了ActionView :: Base.field_error_proc(它上面有一个rails).使用一点nokogiri,我更改了proc,将错误消息添加到input/textarea元素的data-error属性,而不是将它们包装在错误div中.然后,使用jquery写了一个小javascript,将所有输入及其标签包装在文档就绪上.如果存在与输入/ textarea关联的错误信息,则将其传送到包装器div.
我知道这个解决方案依赖于javascript,并且可能有也可能没有优雅的回退,但它在我的情况下工作正常,因为它适用于Web应用程序而不是可公开访问的站点.我认为在那种情况下需要javascript.
# 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
Run Code Online (Sandbox Code Playgroud)
编写自己的ActionView :: Helpers :: FormBuilder
您还可以通过覆盖text_field方法获得或多或少相同的效果,以便它始终返回包装的输入.然后,使用对象变量,访问错误哈希并将任何所需的错误信息添加到包装器.这个不需要javascript并且运行良好,但最后我更喜欢第一种方法,因为我发现它更灵活.但是,如果我在一个可公开访问的网站上工作,我会使用这种方法.
另外,仅供参考,我发现它可以方便地覆盖check_box和radio_button方法,因此它们总是返回带有相关标签的输入.使用自定义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
Run Code Online (Sandbox Code Playgroud)
上面的示例显示了如何包装check_box,但它与text_field大致相同.就像我说的,object.errors如果需要,使用访问错误哈希.这只是冰山的一角......你可以用自定义的FormBuilders做很多事情.
如果您转到自定义表单构建器路径,您可能会发现修改上面的ActionView :: Base.field_error_proc非常有用,因此在出现错误时不会获得双重包装字段.
ActionView::Base.field_error_proc = Proc.new do |html_tag, object|
html_tag # return the html tag unmodified and unwrapped
end
Run Code Online (Sandbox Code Playgroud)
要使用表单构建器,请在form_for方法调用中指定它,或将以下内容放在应用程序助手中:
# application helper
module ApplicationHelper
ActionView::Base.default_form_builder = PrettyFormBuilder
end
Run Code Online (Sandbox Code Playgroud)
通常我的解决方案最终使用每种解决方案的一些组合来实现期望的结果.
| 归档时间: |
|
| 查看次数: |
3987 次 |
| 最近记录: |