Rails Nested Forms using jQuery and SimpleForm
Bài đăng này đã không được cập nhật trong 7 năm
1. Model
Chúng ta có 3 model:
- Stock model: cổ phiếu trên thị trường chứng khoáng.
- Portfolio model: Danh mục đầu tư.(Danh mục đầu tư chứa nhiều tài sản)
- Assets model: Mỗi tài sản có nhiều cổ phiếu.
class Stock < ActiveRecord::Base
has_many :assets
end
class Portfolio < ActiveRecord::Base
has_many :assets
end
class Asset < ActiveRecord::Base
belongs_to :stock
belongs_to :portfolio
end
2. Thêm Nested Attribute
- models/portfolio.rb
class Portfolio < ActiveRecord::Base
belongs_to :user
has_many :assets
attr_accessible :title, :assets_attributes
accepts_nested_attributes_for :assets, allow_destroy: true
end
- controllers/portfolios_controller.rb
class PortfoliosController < ApplicationController
def new
@portfolio = Portfolio.new
@portfolio.assets.build
end
def edit
@portfolio = current_user.portfolios.find params[:id]
@portfolio.assets.build
end
end
3. Giao diện với SimpleForm
- Giao diện cho nested attribute sẽ như sau:
- views/portfolios/_form.html.erb
<%= simple_form_for @portfolio do |f| %>
<%= f.input :title, label: 'Portfolio Title' %>
<%= f.simple_fields_for :assets do |assets_form| %>
<%= assets_form.association :stock %>
<%= assets_form.input :amount, :input_html => { min: 0} %>
<% end %>
<%= f.submit %>
<% end %>
- Đến đây, nếu bạn load form thì nó có thể làm việc tốt. Thế nhưng bạn chỉ có thể tạo một asset form cho một portfolio form. Vì thế, chúng ta sẽ sử dụng jquery để cho người dùng có thể thêm bao nhiêu assets tùy thích.
- Ở đây, chúng ta sẽ đánh dấu các asset form để jquery có thể tìm thấy một cách dễ dàng. Chúng ta sẽ thêm class cho asset form và thêm button "Add Another Asset".
- views/portfolios/_form.html.erb
<%= simple_form_for @portfolio do |f| %>
<%= f.input :title, label: 'Portfolio Title' %>
<%= f.simple_fields_for :assets do |assets_form| %>
< div = "duplicatable_nested_form">
<%= assets_form.association :stock %>
<%= assets_form.input :amount, :input_html => { min: 0 } %>
</div>
<% end %>
<%= link_to 'Add Another Asset', '', class: 'duplicate_nested_form' %>
<%= f.submit %>
<% end %>
4. Sử dụng jquery để thêm asset form
- assets/javascripts/nested_forms.js
$(document).ready(function() {
if $('.duplicatable_nested_form').length > 0 {
nestedForm = $('.duplicatable_nested_form').last().clone(); //Tạo một bản sao của asset form
}
// Bắt sự kiện click button "Add Another Asset"
$(document).on('click', '.duplicate_nested_form', function(e){
e.preventDefault(); // Chặn hoạt động thẻ a
lastNestedForm = $('.duplicatable_nested_form').last(); // Lấy ra asset form cuối cùng
newNestedForm = $(nestedForm).clone();
formsOnPage = $('.duplicatable_nested_form').length; // Lấy số lượng asset form
// Thay đổi label
$(newNestedForm).find('label').each(function(){
oldLabel = $(this).attr('for');
newLabel = oldLabel.replace(new RegExp(/_[0-9]+_/), "_#{formsOnPage}_");
$(this).attr ('for', newLabel);
});
// Thay đổi id, name
$(newNestedForm).find('select, input').each (function(){
oldId = $(this).attr('id');
newId = oldId.replace(new RegExp(/_[0-9]+_/), "_#{formsOnPage}_");
$(this).attr('id', newId);
oldName = $(this).attr('name');
newName = oldName.replace(new RegExp(/\[[0-9]+\]/), "[#{formsOnPage}]");
$(this).attr('name', newName);
});
$( newNestedForm ).insertAfter( lastNestedForm); // Thêm asset form mới
});
})
5. Sử dụng jquery để xóa asset form
- Thêm nút để bắt sự kiện xóa asset form *views/portfolios/_form.html.erb
<%= simple_form_for @portfolio do |f| %>
<%= f.input :title, label: 'Portfolio Title' %>
<%= f.simple_fields_for :assets do |assets_form| %>
< div = "duplicatable_nested_form">
<%= assets_form.association :stock %>
<%= assets_form.input :amount, :input_html => { min: 0 } %>
<%= link_to 'Remove', '', :remote => true, :class => 'destroy_duplicate_nested_form' %>
</div>
<% end %>
<%= link_to 'Add Another Asset', '', class: 'duplicate_nested_form' %>
<%= f.submit %>
<% end %>
- assets/javascripts/nested_forms.js.coffee
// Bắt sự kiện click button "remove"
$(document).on('click', '.destroy_duplicate_nested_form', function(){
$(this).closest('.duplicatable_nested_form').slideUp().remove();
)};
6. Tổng kết
- Nested attributes là một công nghệ mạnh mẽ để phát triển nhanh các forms phức tạp. Và có rất nhiều cách để có thể tận dụng tối đa những gì mà Nested attributes mang lại. Nhưng tôi nghĩ sử dụng jquery sẽ mang lại hiệu quả hơn cho nhưng người mới làm quen với ruby on rails.
Tham khảo: http://davidlesches.com/blog/rails-nested-forms-using-jquery-and-simpleform
All rights reserved