Как получить сгенерированный в Ruby on Rails идентификатор элемента формы для ссылки в JavaScript? - PullRequest
35 голосов
/ 27 января 2011

При использовании помощника 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 %>

Ответы [ 8 ]

22 голосов
/ 27 января 2011

Я закончил тем, что создал собственный конструктор форм для непосредственного предоставления свойства

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 
12 голосов
/ 19 июля 2013

Посмотрите на опции конструктора форм:

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

Опции должны включать как минимум следующие данные: класс css, id, метод http и токен аутентификации.

3 голосов
/ 02 октября 2015

В случае, если у кого-то есть объект 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.

3 голосов
/ 27 января 2011

Вы хотите указать идентификатор самостоятельно.Здесь генерирование идентификатора из object_id формы гарантирует, что оно не будет конфликтовать с другим text_field для имени пользователя в случае вложенных форм.

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

<%= javascript_tag do %>
  $("##{id}").doSomethingReallyCool();
<% end %>
2 голосов
/ 12 октября 2017

В Rails 4.1 мне удалось получить идентификатор с этим:

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

Работает с вложенными формами (fields_for).

0 голосов
/ 08 июля 2017

Я предполагаю, что на странице есть несколько 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 %>   

Затем при отправке я могу получить идентификатор для ввода формы в моих параметрах params[:user][:input_id], который я могу передать js.erb, используя locals.

Надеюсь, это поможет :)

0 голосов
/ 04 июля 2017

Поскольку ваш код Javascript помещен во встроенный файл ruby ​​(.erb), который интерпретируется сервером перед отправкой в ​​браузер клиента, вы можете сгенерировать необходимую переменную JS с помощью фрагмента ruby, например:

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

, а затем используйте его просто как $(id).doSomethingReallyCool();.

Если вам нужно контролировать значение идентификатора, сгенерированного формой в первом случае, вы можете сделать это, передав идентификатор в хеш htmlпараметры:

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.Если эти переменные пришли из формы, поместите их в соответствующие скрытые поля формы.А затем используйте опцию рендера locals, чтобы они были доступны вашему партиалу, например:

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

Если код JS обновляет шаблон, использующий некоторые переменные, используйте тот же подход:

var id='#comment_info_'+<%= n %>
$(id).replaceWith("<%= j (render partial:…, locals: {…}) %>")
0 голосов
/ 25 марта 2011

Мне не очень нравится мое собственное решение, но я старался не идти и исправлять 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...