Как вы получаете идентификатор Ruby on Rails для элемента формы для ссылки в JavaScript?
При использовании вызова form_for
и вызова text_field
Ruby on Rails генерирует уникальный идентификатор для элемента <input />
, который он выдает. Как я могу сгенерировать один и тот же идентификатор для последующего включения в JavaScript, сгенерированный позже?
<%= form_for @user do |f| %>
<%= f.text_field :username %>
<% end %>
Затем на странице:
<%= javascript_tag do %>
$('<%= id of the :username field %>').doSomethingReallyCool();
<% end %>
Ответы
Ответ 1
В итоге я создал настраиваемый конструктор форм, чтобы напрямую открыть свойство
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
Затем установите конструктор форм по умолчанию
ActionView::Base.default_form_builder = FormBuilder
Ответ 2
Посмотрите варианты компоновщика форм:
<%= form_for @user do |f| %>
<% form_css_id = "#" + f.options[:html][:id] %>
<% end %>
Параметры должны включать по меньшей мере следующие данные: класс css, id, метод http и токен аутентификации.
Ответ 3
Вам нужно указать идентификатор самостоятельно. Здесь генерирование id из object_id формы гарантирует, что оно не будет конфликтовать с другим текстовым полем для имени пользователя в случае вложенных форм.
<%= form_for @user do |f| %>
<%- id = "username_#{f.object_id}" %>
<%= f.text_field :username, :id=>id %>
<% end %>
<%= javascript_tag do %>
$("##{id}").doSomethingReallyCool();
<% end %>
Ответ 4
Если у кого-то есть объект FormBuilder из блока fields_for
, получите его id
с помощью этого фрагмента:
<%= form.fields_for :something do |fields_form| %>
<%= fields_form.object_name.gsub(/[/[/]]+/, '_').chop %>id
<% end %>
FieldsForm#object_name
возвращает идентификатор поля как что-то вроде этого: user[address][0]
. Далее, замещение регулярного выражения изменяет группы из одного или нескольких скобок для подчеркивания. Эта замена оставляет конечное подчеркивание, к которому оно добавляет буквы id
. В приведенном выше примере это приводит к user_address_0_id
.
Ответ 5
В Rails 4.1 мне удалось получить идентификатор с этим:
ActionView::Base::Tags::Base.new(
f.object_name,
:username,
:this_param_is_ignored,
).send(:tag_id)
Он работает с вложенными формами (fields_for
).
Ответ 6
Мне не очень нравится мое собственное решение, но я старался не идти и исправлять InstanceTag.
К сожалению, это означало снятие кода санитарии с 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
Ответ 7
Так как ваш Javascript-код помещается в встроенный в Ruby файл (.erb), который интерпретируется сервером перед отправкой в клиентский браузер, вы можете сгенерировать требуемую переменную JS с помощью фрагмента ruby, например:
var id='#id_for_'+<%= @user.username %>
var id='#comment_info_'+<%= n %>
а затем используйте его просто как $(id).doSomethingReallyCool();
.
Если вам нужно контролировать значение идентификатора, сгенерированного формой в первом экземпляре, вы можете сделать это, передав id в хэш-хеш-вариантах:
f.text_field :username, id:"id_for_#{…}"
Если вы используете ненавязчивый подход JS, вы хотели бы поместить JS-код в частичный (.js.erb) и использовать контроллер, если пользовательский клиент разрешает JS. Например:.
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
Это рекомендуемый подход в настоящее время. Проблема в том, что вам нужно передать переменные в ваш JS-код. Если эти переменные пришли из формы, поместите их в подходящие скрытые поля формы. И затем используйте параметр render locals
, чтобы они были доступны вашим частичным, как в:
format.js { render 'foo_doo', locals: {n:n} }
Если код JS обновляет шаблон, который использует некоторые переменные, используйте тот же подход:
var id='#comment_info_'+<%= n %>
$(id).replaceWith("<%= j (render partial:…, locals: {…}) %>")
Ответ 8
Я предполагаю, что на странице есть несколько form_for
, и каждая из них имеет собственную кнопку отправки. Я думаю, именно так я бы сделал это:
Введите скрытое поле в form_for и установите его значение для идентификатора поля ввода. Здесь я выбрал input_#{n}
как идентификатор поля ввода. Конечно, я определяю идентификатор для каждого ввода.
<%= form_for @user do |f| %>
<%= f.text_field :username, id: "input_#{n}" %>
<%= hidden_field_tag 'user[input_id]', value: "input_#{n}" %>
<%= f.submit %>
<% end %>
Затем на submit я могу получить идентификатор формы в моих параметрах params[:user][:input_id]
, которые я могу передать в js.erb
с помощью locals
.
Надеюсь, что это поможет:)