Pregunta ¿Cómo se obtiene el ID generado de Ruby on Rails de un elemento de formulario para referencia en JavaScript?


Al usar el form_for ayudante y a text_field llamada, Ruby on Rails generará una identificación única para el <input /> elemento que produce. ¿Cómo puedo generar la misma identificación para su posterior inclusión en JavaScript generado más adelante?

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

Luego más adelante en la página:

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

32
2018-01-27 17:26


origen


Respuestas:


Terminé creando un generador de formularios personalizado para exponer la propiedad directamente

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

A continuación, configure el generador de formularios predeterminado

ActionView::Base.default_form_builder = FormBuilder 

22
2018-01-27 19:22



Mira las opciones del generador de formularios:

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

Las opciones deben incluir al menos los siguientes datos: clase css, id, método http y token de autenticidad.


12
2017-07-18 20:26



En caso de que alguien tenga un objeto FormBuilder de una fields_for bloquear, obtener su id usando 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 como 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 agrega las letras id. Para el ejemplo proporcionado anteriormente, esto da como resultado user_address_0_id.


3
2017-10-01 23:50



Deberá especificar la identificación usted 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
2018-01-27 17:31



En Rails 4.1 pude obtener la identificación con esto:

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

Funciona con formularios anidados (fields_for)


2
2017-10-12 09:31



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

Desafortunadamente eso significaba levantar el código de desinfecció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

0
2018-03-25 12:43



Dado que su código JavaScript se coloca en un archivo incrustado de ruby ​​(.erb) que está siendo interpretado por el servidor antes de enviarlo al navegador del cliente, puede generar la variable JS requerida con un fragmento de ruby ​​como:

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

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

Si necesita controlar el valor de la ID generada por el formulario en primera instancia, puede hacerlo pasando la identificación en las opciones de hash html:

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

Si está utilizando un enfoque JS discreto, 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 usa el render locals opción para tenerlos disponibles por su parcial, como en:

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

Si el código JS está actualizando una plantilla que usa algunas variables, use el mismo enfoque:

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

0
2017-07-04 18:38



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:

Tener un campo oculto en el form_for y establecer su valor en el id del campo de entrada. Aquí he elegido input_#{n} como la identificación 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, en el envío, puedo obtener el ID de la entrada de formulario en mis parámetros params[:user][:input_id] que puedo pasar a la js.erb utilizando el locals.

Espero que esto ayude :)


0
2017-07-08 14:40