remote rails form_tag example ruby-on-rails ruby parsing dom actionview

ruby on rails - form_tag - Rails-ActionView:: Base.field_error_proc moviendo hacia arriba el árbol DOM



ruby on rails ajax example (1)

¿Hay alguna forma de subir el árbol DOM desde el elemento html_tag pasado?

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

¿Hay alguna forma de implementar este método para mover el árbol DOM y colocar una clase en el div principal?

Por ejemplo:

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

Me gustaría colocar una clase en div.email en lugar de colocar algo directamente en la entrada / etiqueta.

¿Se puede hacer esto con el método field_error_proc o hay una alternativa limpia?

Quiero evitar hacer esto explícitamente en mis puntos de vista en cada campo de formulario. (como el siguiente)

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

FYI: La respuesta corta a mi pregunta es que no hay forma de obtener acceso a porciones adicionales del DOM en el método field_error_proc. Esto se debe al hecho de que estos métodos en realidad no están construyendo un DOM, sino que simplemente combinan un conjunto de cadenas. Para obtener información sobre posibles soluciones, lea las soluciones a continuación.


Tienes dos opciones que puedo pensar en la parte superior de mi cabeza:

Reescribir ActionView :: Base.field_error_proc

En una situación, reescribí ActionView :: Base.field_error_proc (hay una conversión de rieles). Usando un poco de nokogiri, cambié el proceso para agregar los mensajes de error al atributo de error de datos del elemento de entrada / textarea en lugar de envolverlos en un div de error. Luego escribí un pequeño javascript usando jquery para envolver todas las entradas y sus etiquetas en el documento listo. Si hubo información de error asociada con la entrada / textarea, se transfiere a la envoltura div.

Sé que esta solución se basa en JavaScript, y puede que no tenga una caída elegante, pero funciona bien en mi situación, ya que es para una aplicación web en lugar de un sitio de acceso público. Me siento bien requiriendo javascript en ese escenario.

# 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

Escriba su propio ActionView :: Helpers :: FormBuilder

También puede obtener más o menos el mismo efecto anulando el método text_field para que siempre devuelva una entrada envuelta. Luego, usando la variable de objeto, acceda al hash de errores y agregue cualquier información de error necesaria al contenedor. Este no requiere javascript y funciona bien, pero al final prefiero el primer acercamiento porque lo encuentro más flexible. Sin embargo, si estuviera trabajando en un sitio de acceso público, usaría este enfoque en su lugar.

Además, para su información, me pareció útil anular los métodos check_box y radio_button para que siempre devuelvan la entrada con su etiqueta asociada. Hay muchas cosas divertidas que puedes hacer con un FormBuilder personalizado.

# 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

El ejemplo anterior muestra cómo ajustar un check_box, pero es más o menos lo mismo con text_field. Como dije, use los object.errors para acceder al hash de errores si es necesario. Esto es solo la punta del iceberg ... hay mucho que puedes hacer con FormBuilders personalizados.

Si va a la ruta personalizada del creador de formularios, puede resultarle útil modificar el anterior ActionView :: Base.field_error_proc de la siguiente manera, de modo que no obtenga campos envueltos dobles cuando haya errores.

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

Para utilizar el generador de formularios, especifíquelo en la llamada al método form_for o coloque lo siguiente en su ayudante de aplicación:

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

A menudo, mis soluciones terminan usando alguna combinación de cada uno para lograr el resultado deseado.