如何在 JavaScript 中获取 Ruby on Rails 生成的表单元素的 id 以供参考?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4819696/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 14:58:35  来源:igfitidea点击:

How do you get the Ruby on Rails generated id of a form element for reference in JavaScript?

javascriptruby-on-railsforms

提问by Paul Alexander

When using the form_forhelper and a text_fieldcall, Ruby on Rails will generate a unique id for the <input />element that it outputs. How can I generate the same id for later inclusion into JavaScript generated later?

使用form_for帮助程序和text_field调用时,Ruby on Rails 将为<input />它输出的元素生成唯一的 id 。如何生成相同的 id 以便稍后包含到稍后生成的 JavaScript 中?

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

Then later in the page:

然后在页面后面:

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

采纳答案by Paul Alexander

I ended up creating a custom form builder to expose the property directly

我最终创建了一个自定义表单构建器来直接公开该属性

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

Then set the default form builder

然后设置默认的表单构建器

ActionView::Base.default_form_builder = FormBuilder 

回答by Matt Aimonetti

Look at the form builder options:

查看表单构建器选项:

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

Options should at least include the following data: css class, id, http method and authenticity token.

选项至少应包括以下数据:css 类、id、http 方法和真实性令牌。

回答by rodamn

In case someone has a FormBuilder object from a fields_forblock, get its idusing this snippet:

如果有人从fields_for块中获得FormBuilder 对象,请id使用以下代码段获取它:

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

FieldsForm#object_namereturns the field's ID as something like this: user[address][0]. Next, the regex substitution changes groups of one or more brackets to underscores. This substitution leaves a trailing underscore, to which it appends the letters id. For the example provided before, this results in user_address_0_id.

FieldsForm#object_name像这样返回字段的 ID:user[address][0]。接下来,正则表达式替换将一个或多个括号的组更改为下划线。这种替换会留下一个尾随下划线,并在其上附加字母id。对于之前提供的示例,这将导致user_address_0_id.

回答by Jesse Wolgamott

You'll want to specify the id yourself. Here generating the id from the object_id of the form guarantees that it won't conflict with another text_field for username in the case of nested forms.

您需要自己指定 id。这里从表单的 object_id 生成 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 %>

回答by Micha?l Witrant

In Rails 4.1 I was able to get the id with this:

在 Rails 4.1 中,我能够通过以下方式获得 id:

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

It works with nested forms (fields_for).

它适用于嵌套表单 ( fields_for)。

回答by ilpoldo

I don't really like my own solution that much, but I tried not to go and patch InstanceTag.

我不太喜欢我自己的解决方案,但我尽量不去修补 InstanceTag。

Unfortunately that meant lifting the sanitization code from ActionView::Helpers::InstanceTagMethods

不幸的是,这意味着从 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

回答by Claudio Floreani

Since your Javascript code is placed in a ruby embedded file (.erb) that is being interpreted by the server before being sent to the client browser, you can generated the required JS variable with a ruby snippet like:

由于您的 Javascript 代码被放置在一个 ruby​​ 嵌入文件 (.erb) 中,该文件在发送到客户端浏览器之前由服务器解释,您可以使用如下 ruby​​ 片段生成所需的 JS 变量:

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

and then use it simply as $(id).doSomethingReallyCool();.

然后将其简单地用作$(id).doSomethingReallyCool();.

If you need to control the value of the id generated by the form in first instance, you can do it passing the id in the html hash options:

如果您需要首先控制表单生成的 id 的值,您可以在 html 哈希选项中传递 id:

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

If you're using a unobtrusive JS approach, you would like to place the JS code into a partial (.js.erb) and have the controller use it if the user client allows JS. E.g.:

如果您使用不显眼的 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

This is the recommended approach nowadays. The problem now is that you need to pass the variables to your JS code. If these variables came from a form, place them in opportune hidden form fields. And then use the render's localsoption to have them available by your partial, as in:

这是目前推荐的方法。现在的问题是您需要将变量传递给您的 JS 代码。如果这些变量来自表单,请将它们放在合适的隐藏表单字段中。然后使用渲染的locals选项让您的部分可用,如下所示:

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

If the JS code is updating a template that use some variables, use the same approach:

如果 JS 代码正在更新使用某些变量的模板,请使用相同的方法:

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

回答by dhaliman

I assume that there are multiple form_forin the page and each has it's own submit button. I think this is how I would do this:

我假设页面中有多个form_for,每个都有自己的提交按钮。我想这就是我要这样做的方式:

Have a hidden field in the the form_for and set it's value to the id of the input field. Here I've chosen input_#{n}as the id of the input field. Of course I'll define the id for each input.

在 form_for 中有一个隐藏字段,并将其值设置为输入字段的 id。在这里,我选择了input_#{n}作为输入字段的 id。当然,我会为每个输入定义 id。

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

Then on submit I can get the id the form input in my params params[:user][:input_id]which I can pass to the js.erbusing the locals.

然后在提交时,我可以在我的参数中获取表单输入的 id params[:user][:input_id],我可以将其传递给js.erb使用locals.

Hope this helps :)

希望这可以帮助 :)