Tìm hiểu gem Cocoon Rails
This post hasn't been updated for 8 years
Cocoon giúp cho xử lý các form
lồng nhau nó dễ dàng hơn.
Ví dụ. một project
với nhiều tasks
.
Cocoon tương thích với Rails 3 và Rails 4.
Yêu cầu
Gem này phụ thuộc vào jQuery
, vì vậy nó là hữu ích nhất trong một dự án Rails 3
mà bạn đang sử dụng jQuery
. Hơn nữa, tôi sẽ khuyên bạn nên sử dụng một trong hai Formtastic
vs Simple_Form
.
Cài đặt
Thêm vào trong Gemfile
gem "cocoon"
Xin lưu ý rằng cho Rails 4, bạn sẽ cần ít nhất v1.2.0 hoặc sau đó.
Rails 3.1+/Rails 4
Thêm dòng sau vào application.js
//= require cocoon
Rails 3.0.x
Nếu bạn đang sử dụng Rails 3.0.x, bạn cần để chạy lệnh sau để cài đặt (từ Rails 3.1 điều này không còn cần thiết):
rails g cocoon:install
Lệnh này sẽ cài đặt Cocoon JavaScript. Trong application.js
thêm vào:
= javascript_include_tag :cocoon
Sử dụng cơ bản
Giả sử bạn có một model là Project
rails g scaffold Project name:string description:string
Và project
có nhiều tasks
rails g model Task description:string done:boolean project:belongs_to
Thiết lập relation giữa các models
class Project < ActiveRecord::Base
has_many :tasks
accepts_nested_attributes_for :tasks, reject_if: :all_blank, allow_destroy: true
end
class Task < ActiveRecord::Base
belongs_to :project
end
Bây giờ form
project có thể thêm hoặc xóa các tasks
. Để làm được vậy chúng ta cần có cá tasks
của project
hoặc tạo mới, form
task được định nghĩa là một partial _task_fields.html
.
Strong Parameters
Để xóa các fields
với nested model, chúng ta sử dụng một virtual attribute tên là _destroy
. Khi mà _destroy
được thiết lập thì nested model sẽ được xóa.
Định nghĩa trong controller
.
Ví dụ chúng ta định nghĩa trong projects_controller.rb
như sau:
def project_params
params.require(:project).permit(:name, :description, tasks_attributes: [:id, :description, :done, :_destroy])
end
Ví dụ
Cocoon sử dụng mặc định link_to_add_association
để thêm mới một nested_field. và link_to_remove_association
để remove nested_field.
Formtastic
Trong projects/_form
partial chúng ta viết:
= semantic_form_for @project do |f|
= f.inputs do
= f.input :name
= f.input :description
%h3 Tasks
#tasks
= f.semantic_fields_for :tasks do |task|
= render 'task_fields', f: task
.links
= link_to_add_association 'add task', f, :tasks
= f.actions do
= f.action :submit
Và trong _task_fields partial
viết như sau:
.nested-fields
= f.inputs do
= f.input :description
= f.input :done, as: :boolean
= link_to_remove_association "remove task", f
SimpleForm
Trong projects/_form
partial chúng ta viết:
= simple_form_for @project do |f|
= f.input :name
= f.input :description
%h3 Tasks
#tasks
= f.simple_fields_for :tasks do |task|
= render 'task_fields', f: task
.links
= link_to_add_association 'add task', f, :tasks
= f.submit
Và trong _task_fields partial
viết như sau:
.nested-fields
= f.input :description
= f.input :done, as: :boolean
= link_to_remove_association "remove task", f
Standard Rails forms
Trong projects/_form
partial chúng ta viết:
= form_for @project do |f|
.field
= f.label :name
%br
= f.text_field :name
.field
= f.label :description
%br
= f.text_field :description
%h3 Tasks
#tasks
= f.fields_for :tasks do |task|
= render 'task_fields', f: task
.links
= link_to_add_association 'add task', f, :tasks
= f.submit
Và trong _task_fields partial
viết như sau:
.nested-fields
.field
= f.label :description
%br
= f.text_field :description
.field
= f.check_box :done
= f.label :done
= link_to_remove_association "remove task", f
Tìm hiểu về cách làm việc
Cocoon định nghĩa 2 hành vi cơ bản là link_to_add_association
và link_to_remove_association
.
link_to_add_association
Chức năng này dùng để thêm mới field
partial vào trong form.
Cú pháp:
= link_to_add_association 'add something', f, :something,
render_options: { wrapper: 'inline' }
Với cú pháp trên nó sẽ tự động nhận partial
trong thư mục là views/tasks
(đối với trong bài viết này.)
Để sử dụng partial
ở chỗ khác dùng chung ví dụ ở shared
chẳng hạn thì cú pháp như sau
= link_to_add_association 'add something', f, :something,
partial: 'shared/something_fields'
link_to_remove_association
Chức năng này dùng để remove field partial
Cú pháp
= link_to_remove_association "remove task", f
Events Javascript
Cocoon cung cấp một số event như sau:
cocoon:before-insert: called before inserting a new nested child
cocoon:after-insert: called after inserting
cocoon:before-remove: called before removing the nested child
cocoon:after-remove: called after removal
Để lắng nghe event với javascript ví dụ như sau:
$('#container').on('cocoon:before-insert', function(e, insertedItem) {
// ... do something
});
Với trường hợp là các tasks
ở bài viết này thì chúng ta có thể sử dụng như sau:
$(document).ready(function() {
$('#tasks')
.on('cocoon:before-insert', function(e,task_to_be_added) {
task_to_be_added.fadeIn('slow');
})
.on('cocoon:after-insert', function(e, added_task) {
// e.g. set the background of inserted task
added_task.css("background","red");
})
.on('cocoon:before-remove', function(e, task) {
// allow some time for the animation to complete
$(this).data('remove-timeout', 1000);
task.fadeOut('slow');
});
});
I18n
Sử dụng I18n
với Cocoon ví dụ như sau:
en:
cocoon:
defaults:
add: "Add record"
remove: "Remove record"
tasks:
add: "Add new task"
remove: "Remove old task"
Khi đó chúng ta có thể sử dụng lệnh này
= link_to_add_association form_object, :tasks
= link_to_remove_association form_object
Thay vì dùng như sau
= link_to_add_association "Add task", form_object, :tasks
= link_to_remove_association "remove task", form_object
Cảm ơn bạn đọc đã xem bài viết.
Bài viết được dịch từ địa chỉ:
All Rights Reserved