12/08/2018, 13:44

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

0