1 分鐘閱讀

前言

Cocoon可以方便快速建立動態Nested Form,避免手動寫一堆jQuery, 適合懶人、新手、不想用前端框架之人。

使用方式

# [path] gemfile
gem "cocoon"
// [path] application.js
//= require cocoon

基本用法

假設你有一個Project model:

rails g scaffold Project name:string description:string

而且這個 project 有很多 tasks:

rails g model Task description:string done:boolean project:belongs_to

你的模型是這樣關聯的:

class Project < ActiveRecord::Base
  has_many :tasks, inverse_of: :project
  accepts_nested_attributes_for :tasks, reject_if: :all_blank, allow_destroy: true
end

class Task < ActiveRecord::Base
  belongs_to :project
end

現在我們需要一個可以動態新增和刪除任務的項目表單。

為此,我們需要一個新的或現有的 partial 取名為 _task_fields.html

params驗證部分需要加入

# [path] ProjectsController
 def project_params
    params.require(:project).permit(:name, :description, tasks_attributes: [:id, :description, :done, :_destroy])
  end

範例

Cocoon預設要求使用link_to_add_association helper新增項目, 並將每個項目部份用partial包裝。下面的例子說明了簡單的佈局。

這邊使用SimpleForm舉例

<!-- [path] projects/_form -->
<%= simple_form_for @project do |f| %>
  <%= f.input :name %>
  <%= f.input :description %>
  <h3>Tasks</h3>
  <div id="tasks">
    <%= f.simple_fields_for :tasks do |task| %>
      <%= render 'task_fields', f: task %>
    <% end %>
    <div class="links">
      <%= link_to_add_association 'add task', f, :tasks %>
    </div>
  </div>
  <%= f.submit %>
<% end %>

另外,我們需要新增 _task_fields 這個partial

<div class="nested-fields">
  <%= f.input :description %>
  <%= f.input :done, as: :boolean %>
  <%= link_to_remove_association "remove task", f %>
</div>

可以參考此範例 cocoon_simple_form_demo

Helper使用方式

###link_to_add_association

參數 說明
name String  
f from builder  
association from builder 需要添加新實例的關聯(複數)的名稱(符號或字符串)
html_options 額外的html選項(參見link_to)  
data-association-insertion-traversal closest,next,children jquery遍歷方法允許相對於鏈接的節點選擇。
data-association-insertion-node 默認值:父節點 將節點的jquery選擇器作為字符串,或者以link_to_add_association節點為參數並返回節點的函數
data-association-insertion-method before,after,append,prepend,等默認值:before 插入新數據的jquery方法。
partial String 明確聲明將要使用的partial的名稱
render_options String 傳遞給表單構建器函數的選項(例如simple_fields_for,semantic_fields_for或fields_for)。如果它包含一個:locals包含哈希的選項,那麼它將被傳遞給部分。
wrap_object 一個允許包裝對象的proc,特別是在使用裝飾器(例如draper)時很有用。見下面的例子。  

例如:指定partial和產生項目的地方 <%= link_to_add_association ‘新增’, f, :barcodes, partial: ‘stock/products/forms/barcode/form_barcode’, ‘data-association-insertion-method’ => ‘before’, ‘data-association-insertion-node’ => ‘.panel-items’, ‘data-association-insertion-traversal’ => ‘closest’ %>

參數 說明
name String  
f from builder  
html_options 額外的html選項(參見link_to)  

例如: 可以使用wrapper_class指定刪除的部份(原本預設是nested-fields)

<div class="barcode-fields">
  <%= f.input :description %>
  <%= f.input :done, as: :boolean %>
  <%= link_to_remove_association "remove task", f, wrapper_class: 'barcode-fields' %>
</div>

參考

  1. cocoon
  2. append item to designated position
  3. delete not working

更新時間:

留言