Tìm hiểu gem Cocoon Rails
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 ...
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ỉ:
https://github.com/nathanvda/cocoon