Nested form fields trong rails
Bài đăng này đã không được cập nhật trong 7 năm
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"}
Tài liệu tham khảo
Bài viết này mình có tham khảo tại địa chỉ trang web sau, rất mong nhận được sự đóng góp ý kiến của các bạn để bài viết của mình có thể hoàn thiện hơn nữa
All rights reserved