2011-01-27 17 views
31

Cuando se utiliza el form_for ayudante y una llamada text_field, Ruby on Rails generará un identificador único para el elemento <input /> que produzca. ¿Cómo puedo generar la misma identificación para su posterior inclusión en JavaScript generado más adelante?¿Cómo se obtiene el ID generado de Ruby on Rails de un elemento de formulario para referencia en JavaScript?

<%= form_for @user do |f| %> 
    <%= f.text_field :username %> 
<% end %> 

Luego, más tarde en la página:

<%= javascript_tag do %> 
    $('<%= id of the :username field %>').doSomethingReallyCool(); 
<% end %> 
+0

Me gustaría señalar que el ejemplo adicional en la recompensa es solo otro caso particular en el que la respuesta será útil. No es una pregunta diferente. Para ser aceptable, la respuesta debería ser un propósito general suficiente para ajustarse tanto al ejemplo original como al mío. Ambos ejemplos muestran un caso en el que es necesario "obtener el ID generado de Ruby on Rails de un elemento de formulario para referencia en JavaScript". –

+0

Meta pregunta sobre la recompensa actual https://meta.stackoverflow.com/q/351561/73226 –

+2

@ClaudioFloreani No, eso no está bien. Tenga en cuenta que el texto de su recompensa ya no es visible después de que la recompensa expira o se otorga. Una respuesta que aborde la pregunta en tu generosidad tendrá muy poco sentido después de que la recompensa haya desaparecido. Por favor haga una nueva pregunta. – duskwuff

Respuesta

22

que acabó creando un constructor de formulario personalizado para exponer directamente con el establecimiento

class FormBuilder < ActionView::Helpers::FormBuilder 
    def id_for(method, options={}) 
    InstanceTag.new(object_name, method, self, object) \ 
       .id_for(options)    
    end 
end 

class InstanceTag < ActionView::Helpers::InstanceTag 
    def id_for(options) 
    add_default_name_and_id(options) 
    options['id'] 
    end 
end 

asentando después el formulario predeterminado constructor

ActionView::Base.default_form_builder = FormBuilder 
+0

¡Agradable, gracias! ¿Dónde está el mejor lugar para poner esto en una aplicación de Rails? –

+0

Mike: un archivo config/initializers/{file_name} .rb haría el truco –

+0

Tengo problemas para conceptualizar cómo se llama esto. Demasiado meta para mi cerebro, supongo. ¿Podría dar un ejemplo simple? –

3

usted querrá para especificar el ID de sí mismo. Aquí la generación de la identificación desde el object_id del formulario garantiza que no entrará en conflicto con otro text_field para username en el caso de formularios anidados.

<%= form_for @user do |f| %> 
    <%- id = "username_#{f.object_id}" %> 
    <%= f.text_field :username, :id=>id %> 
<% end %> 

<%= javascript_tag do %> 
    $("##{id}").doSomethingReallyCool(); 
<% end %> 
+3

Esto no es realmente una opción en este caso, ya que los campos JavaScript y de formulario son dinámicos y no necesariamente tendré la capacidad de controlar la llamada 'f.text_field'. –

+0

Esa es una respuesta obvia a un caso particular en el que la aplicación Rails no genera dinámicamente el ID. –

0

que no me gusta mucho mi propia solución que mucho, pero traté de no ir y aplicarle un parche a InstanceTag.

desgracia que significaba levantar el código de sanitización de ActionView::Helpers::InstanceTagMethods

class MyCoolFormBuilder < ActionView::Helpers::FormBuilder 
    def sanitized_object_name 
     @sanitized_object_name ||= object_name.gsub(/\]\[|[^-a-zA-Z0-9:.]/, "_").sub(/_$/, "") 
    end 

    def field_id_for(method) 
     "#{sanitized_object_name}_#{method.to_s.sub(/\?$/,"")}" 
    end 
end 
12

vistazo a las opciones creador de formularios:

<%= form_for @user do |f| %> 
    <% form_css_id = "#" + f.options[:html][:id] %> 
<% end %> 

opciones deben incluir al menos los siguientes datos: clase CSS, identificación, método HTTP y token de autenticidad

+3

f.options [: html] es nulo para mí. – Trejkaz

+0

¡No es nada para mí! Desearía poder votar esto más. Esto es especialmente útil con el nuevo atributo de "forma" de HTML5. Pruebe esto: '<% f.submit" Guardar cambios ", formulario: f.options [: html] [: id]%>'. Ahora puede usar javascript para mover ese formulario a cualquier lugar que desee, y aún así funcionará para enviar el formulario. ¡Tan agradable! – Ziggy

+0

Parece nulo para objetos anidados, pero en el formulario principal funciona bien. – Romuloux

2

En caso de que alguien tiene un objeto FormBuilder de un bloque fields_for, obtener su id utilizando este fragmento:

<%= form.fields_for :something do |fields_form| %> 
    <%= fields_form.object_name.gsub(/[/[/]]+/, '_').chop %>id 
<% end %> 

FieldsForm#object_name devuelve el ID del campo como algo parecido a esto: user[address][0]. A continuación, la sustitución de expresiones regulares cambia los grupos de uno o más paréntesis para subrayar. Esta sustitución deja un guión bajo final, al que se anexan las letras id. Para el ejemplo proporcionado anteriormente, esto da como resultado user_address_0_id.

0

Debido a que su código Javascript se coloca en un archivo incrustado rubí (.erb) que está siendo interpretado por el servidor antes de ser enviado al navegador del cliente, puede generada la variable JS requerida con un fragmento de rubí como:

var id='#id_for_'+<%= @user.username %> 
var id='#comment_info_'+<%= n %> 

y luego usarlo simplemente como $(id).doSomethingReallyCool();.

Si necesita controlar el valor del identificador generado por la forma en primera instancia, se puede hacer pasar el id en las opciones de hash html:

f.text_field :username, id:"id_for_#{…}" 

Si estás utilizando un JS discreta Enfoque, le gustaría colocar el código JS en un parcial (.js.erb) y hacer que el controlador lo use si el cliente usuario permite JS. P.ej.:

class FooController < ApplicationController 

def foo_doo 
    … # some logic 
    respond_to do |format| 
    format.js # this will render javascript in file “foo_doo.js.erb” if allowed 
    format.html { … } # html fallback for unobtrusive javascript 
    end 
end 

Este es el enfoque recomendado hoy en día. El problema ahora es que necesita pasar las variables a su código JS. Si estas variables provienen de un formulario, colóquelas en campos de formulario ocultos oportunos. Y luego usar el de hacer que locals opción de tener a disposición por su parcial, como en:

format.js { render 'foo_doo', locals: {n:n} } 

Si el código JS es la actualización de una plantilla que utilice algunas variables, utilizar el mismo enfoque:

var id='#comment_info_'+<%= n %> 
$(id).replaceWith("<%= j (render partial:…, locals: {…}) %>") 
0

Supongo que hay múltiples form_for en la página y cada uno tiene su propio botón de envío. Creo que así es como haría esto:

Tenga un campo oculto en el form_for y establezca su valor en el id del campo de entrada. Aquí he elegido input_#{n} como ID del campo de entrada. Por supuesto, definiré la identificación para cada entrada.

<%= form_for @user do |f| %> 
    <%= f.text_field :username, id: "input_#{n}" %> 
    <%= hidden_field_tag 'user[input_id]', value: "input_#{n}" %> 
    <%= f.submit %> 
<% end %> 

Luego de enviar puedo conseguir el ID de la entrada de un formulario en mis params params[:user][:input_id] que puedo pasar a la js.erb utilizando el locals.

Espero que esto ayude :)

1

En Rails 4.1 que fue capaz de obtener el id con esto:

ActionView::Base::Tags::Base.new(
    f.object_name, 
    :username, 
    :this_param_is_ignored, 
).send(:tag_id) 

Funciona con formas anidadas (fields_for).

Cuestiones relacionadas