12/08/2018, 14:25

Nested form fields trong rails

Là một gem của rails giúp tạo ra form cho model cùng với quan hệ nested has_many Gem này sử dụng JQuery để tự động thêm vào xóa đi quan hệ nested Làm việc với các quan hệ nested lồng nhau (có thể lên đến mức 4) Làm việc cùng với form builders giống như simple_form Yêu cầu ruby 1.9 trở lên ...

Là một gem của rails giúp tạo ra form cho model cùng với quan hệ nested has_many Gem này sử dụng JQuery để tự động thêm vào xóa đi quan hệ nested

  • Làm việc với các quan hệ nested lồng nhau (có thể lên đến mức 4)
  • Làm việc cùng với form builders giống như simple_form
  • Yêu cầu ruby 1.9 trở lên

Cài đặt

Thêm dòng này vào Gemfile trong ứng dụng của bạn

gem "nested_form_fields"

và chạy lệnh

$ bundle

Trong file application.js của ứng dụng bạn thêm vào dòng sau để có thể sử dụng được file nested_form_fields.js.coffee //= require nested_form_fields

Sử dụng

Giả sử bạn có model User cùng với nested videos:

class User < ActiveRecord::Base
  has_many :videos
  accepts_nested_attributes_for :videos, allow_destroy: true
end

Sử dụng nested_fields_for hepler bên trong user form của bạn để thêm vào các videos

= form_for user do |f|
  = f.nested_fields_for :videos do |ff|
    = ff.text_field :video_title
    ..

Đường link để thêm và xóa các field là add_nested_fields_link and remove_nested_fields_link

= form_for user do |f|
  = f.nested_fields_for :videos do |ff|
    = ff.remove_nested_fields_link
    = ff.text_field :video_title
    ..
  = f.add_nested_fields_link :videos

Chú ý rằng remove_nested_fields_link được gọi bên trong nested_fields_for và add_nested_fields_link được gọi từ bên ngoài thông qua parent builder.

Sửa đổi link

Chúng ta có thể thay đổi tên link của remove_nested_fields_link và add_nested_fields_link như thế này:

...
  ff.remove_nested_fields_link "Remove me"
  ...
f.add_nested_fields_link :videos, "Add another funtastic video"

Chúng ta có thể thêm class/addtributes vào remove_nested_fields_link and add_nested_fields_link giống như:

...
  ff.remove_nested_fields_link "Remove me", class: "btn btn-danger", role: "button"
  ...
f.add_nested_fields_link :videos, "Add another funtastic video", class: "btn btn-primary", role: "button"

Bạn có thể thêm vào một khối vào remove_nested_fields_link và the add_nested_fields_link như thể bạn dùng link_to

= ff.remove_nested_fields_link do
  Remove me %span.icon-trash

Bạn có thể thêm vào thuộc tính data-confirm vào remove_nested_fields_link nếu bạn muốn người dùng confirm bất kể khi nào họ muốn xóa một nested field:

= ff.remove_nested_fields_link "Remove me", data: {confirm: "Are you sure?"}

Custom Container

Bạn có thể định nghĩa một custom container để thêm vào trong nested forms bằng cách cung cấp một id thông qua thuộc tính data-insert-into của add_nested_fields_link:

f.add_nested_fields_link :videos, "Add another funtastic video", data: {insert_into: "<container_id>"}

Custom Fields Wrapper

Bạn có thể thay đổi kiểu của các phần tử wrapping trong nested fields sử dụng thuộc tính wrapper_tag:

= f.nested_fields_for :videos, wrapper_tag: :div do |ff|

Các phần tử wrapper mặc định là một fieldset. Để thêm phần tử legend vào fieldset thì sử dụng:

= f.nested_fields_for :videos, legend: "Video" do |ff|

Bạn có thể dùng wrapper_options để truyền vào một hash các lựa chọn, giống như bạn sử dụng phương thức content_tag

= f.nested_fields_for :videos, wrapper_options: {class: "row"} do |ff|

Parameter trong rails 4

Trong rails 4 để truyền về các params bạn phải khai báo {{ NESTED_MODEL }}_attributes trong controller. Nếu bạn muốn xóa các nested model bạn nên thêm vào :_destroy and :id. Ví dụ:

# app/views/users/_form.haml.erb
= form_for user do |f|
  = f.nested_fields_for :videos do |ff|
    = ff.remove_nested_fields_link
    = ff.text_field :video_title
    ..
  = f.add_nested_fields_link :videos
# app/controllers/users_controller
..
def user_params
    params.require(:user)   .permit(:name,:email,videos_attributes[:video_title,:_destroy,:id])
end

Sự kiện

Có 4 sự kiện javascript trước và sau khi thêm/xóa các field trong nested_form_fields tên là:

  • fields_adding
  • fields_added
  • fields_removing
  • fields_removed

Sự kiện fields_added and fields_removed được trigger trên phần tử khi đang được thêm hoặc xóa bỏ. Dễ dàng để thêm các listener khi mà có nhiều nested_form_fields trên những các trang tương tự nhau.

Ví dụ CoffeeScript:

# Listen on an element
initializeSortable -> ($el)
  $el.sortable(...)
  $el.on 'fields_added.nested_form_fields', (event, param) ->
    console.log event.target # The added field
    console.log $(this)      # $el

# Listen on document
$(document).on "fields_added.nested_form_fields", (event, param) ->
  switch param.object_class
    when "video"
      console.log "Video object added"
    else
      console.log "INFO: Fields were successfully added, callback not handled."

Bạn có thể truyền bất kỳ dữ liệu mở rộng nào trong sự kiện callback

# Trigger button click programmatically and pass an object `{hello: 'world'}`
$('.add_nested_fields_link').trigger('click', [{hello: "world"}])

# Listen for the event
$(document).on "fields_added.nested_form_fields", (event, param) ->
  console.log param.additional_data #=> {hello: "world"}

0