Pertanyaan Bagaimana Anda mendapatkan Ruby on Rails menghasilkan id dari elemen formulir untuk referensi di JavaScript?


Saat menggunakan form_for pembantu dan a text_field panggilan, Ruby on Rails akan menghasilkan id unik untuk <input /> elemen yang dihasilkannya. Bagaimana saya bisa menghasilkan id yang sama untuk kemudian dimasukkan ke dalam JavaScript yang dihasilkan nanti?

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

Kemudian di halaman selanjutnya:

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

32
2018-01-27 17:26


asal


Jawaban:


Saya akhirnya membuat pembuat formulir khusus untuk mengekspos properti secara langsung

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

Kemudian setel bentuk pembangun default

ActionView::Base.default_form_builder = FormBuilder 

22
2018-01-27 19:22



Lihatlah opsi form builder:

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

Pilihan setidaknya harus menyertakan data berikut: kelas css, id, metode http dan token keaslian.


12
2017-07-18 20:26



Jika seseorang memiliki objek FormBuilder dari fields_for blokir, dapatkan id menggunakan potongan ini:

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

FieldsForm#object_name mengembalikan ID bidang sebagai sesuatu seperti ini: user[address][0]. Selanjutnya, substitusi regex mengubah kelompok dari satu atau lebih kurung ke garis bawah. Substitusi ini meninggalkan garis bawah yang menggarisbawahi, di mana ia menambahkan huruf-huruf id. Untuk contoh yang diberikan sebelumnya, ini menghasilkan user_address_0_id.


3
2017-10-01 23:50



Anda harus menentukan sendiri ID itu. Di sini menghasilkan id dari object_id dari form menjamin bahwa ia tidak akan berkonflik dengan text_field lain untuk nama pengguna dalam hal bentuk bersarang.

<%= 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



Di Rails 4.1 saya bisa mendapatkan id dengan ini:

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

Ia bekerja dengan bentuk bersarang (fields_for).


2
2017-10-12 09:31



Saya tidak terlalu suka solusi saya sendiri, tetapi saya mencoba untuk tidak mem-patch InstanceTag.

Sayangnya itu berarti mengangkat kode sanitasi dari 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



Karena kode Javascript Anda ditempatkan dalam file tertanam ruby ​​(.erb) yang sedang ditafsirkan oleh server sebelum dikirim ke browser klien, Anda dapat menghasilkan variabel JS yang diperlukan dengan cuplikan ruby ​​seperti:

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

dan kemudian menggunakannya hanya sebagai $(id).doSomethingReallyCool();.

Jika Anda perlu mengontrol nilai id yang dihasilkan oleh formulir dalam contoh pertama, Anda dapat melakukannya dengan meneruskan id di opsi html hash:

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

Jika Anda menggunakan pendekatan JS tidak mengganggu, Anda ingin menempatkan kode JS menjadi parsial (.js.erb) dan memiliki pengontrol menggunakannya jika klien pengguna memungkinkan JS. Misalnya.:

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

Ini adalah pendekatan yang direkomendasikan saat ini. Masalahnya sekarang adalah Anda harus meneruskan variabel ke kode JS Anda. Jika variabel-variabel ini berasal dari suatu bentuk, tempatkan mereka dalam bidang formulir tersembunyi yang menguntungkan. Dan kemudian gunakan render locals pilihan untuk memilikinya tersedia secara parsial Anda, seperti pada:

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

Jika kode JS memperbarui template yang menggunakan beberapa variabel, gunakan pendekatan yang sama:

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

0
2017-07-04 18:38



Saya berasumsi bahwa ada beberapa form_for di halaman dan masing-masing memiliki tombol submit sendiri. Saya pikir ini adalah bagaimana saya akan melakukan ini:

Miliki bidang tersembunyi di form_for dan tetapkan nilainya ke id dari field input. Di sini saya telah memilih input_#{n} sebagai id dari kolom input. Tentu saja saya akan menentukan id untuk setiap input.

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

Kemudian pada submit saya bisa mendapatkan id berupa input di params saya params[:user][:input_id] yang bisa saya berikan kepada js.erb menggunakan locals.

Semoga ini membantu :)


0
2017-07-08 14:40