Rails - ActionView :: Base.field_error_proc перемещается вверх по дереву DOM? - PullRequest
8 голосов
/ 08 сентября 2011

Есть ли какой-нибудь способ перейти вверх по дереву DOM из переданного элемента html_tag?

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

Можно ли как-нибудь реализовать этот метод для перемещения вверх по дереву 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>

Я бы хотел разместить класс на div.email, а не размещать что-либо непосредственно на входе / метке.

Можно ли это сделать с помощью метода field_error_proc или есть чистая альтернатива?

Я хочу избегать делать это явно в моих взглядах на каждое поле формы. (как показано ниже)

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

К вашему сведению: Короткий ответ на мой вопрос заключается в том, что нет способа получить доступ к дополнительным частям DOM в методе field_error_proc. Это связано с тем, что эти методы на самом деле не строят DOM, а просто объединяют кучу строк вместе. Для получения информации о некоторых возможных обходных путях прочитайте приведенные ниже решения.

1 Ответ

15 голосов
/ 08 сентября 2011

У вас есть два варианта, которые я могу придумать: «1001 *»

Переписать ActionView :: Base.field_error_proc

В одной ситуации я переписал ActionView :: Base.field_error_proc (на него наложены рельсы). Используя немного нокогири, я изменил процедуру, добавив сообщения об ошибках в атрибут data-error элемента input / textarea, вместо того, чтобы заключать их в div ошибки. Затем я написал небольшой javascript, используя jquery, чтобы обернуть все входные данные и их метки в готовом документе. Если с вводом / текстовой областью была связана информация об ошибке, она передается в разделитель оболочки.

Я знаю, что это решение основано на javascript и может иметь или не иметь плавного отката, но в моей ситуации оно работает нормально, поскольку оно предназначено для веб-приложения, а не для общедоступного сайта. Я чувствую себя хорошо, требуя 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

Написать свой собственный 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

В приведенном выше примере показано, как обернуть флажок check_box, но он более или менее совпадает с полем text_. Как я уже сказал, используйте 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

Чтобы использовать построитель форм, либо укажите его в вызове метода form_for, либо поместите в помощник приложения следующее:

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

Часто мои решения заканчиваются использованием некоторой комбинации каждого для достижения желаемого результата.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...