2013-02-08 17 views
6

tôi là tạo ra một danh sách các hộp kiểm cho một bộ sưu tập duy nhất như vậy:Thêm một thuộc tính dữ liệu giá trị phụ thuộc vào một bộ sưu tập hộp kiểm simple_form

= f.input :parts, as:check_boxes, collection: @parts_list 

Tôi muốn có một số hộp kiểm trong bộ sưu tập để biến mất/tái xuất hiện tùy thuộc vào giá trị của một tiện ích con chọn cao hơn trong biểu mẫu. (ví dụ: chọn "Robot theo dõi" từ Robot chọn có nghĩa là hộp kiểm "Chân" sẽ biến mất và hộp kiểm "Bánh xe" xuất hiện, v.v.)

Điều tôi muốn làm là gắn thuộc tính dữ liệu được tính vào mỗi hộp kiểm Phần riêng lẻ, với giá trị thuộc tính liệt kê các Robot có thể sử dụng Phần đó; thì một số JS sẽ thực hiện công việc ẩn/hiện các hộp kiểm. Tuy nhiên, tôi không biết làm thế nào tôi có thể tạo ra những thuộc tính dữ liệu bằng cách sử dụng simple_form.

Tôi thường tạo một đầu vào "phần" tùy chỉnh, nhưng dường như có vấn đề với việc tạo các đầu vào bộ sưu tập tùy chỉnh; nó tìm kiếm một phương thức có tên (collection_parts) bên trong form_builder.rb, nó sẽ không tồn tại, và nếu tôi thử và mở rộng FormBuilder nó sẽ gửi cho tôi một lỗ thỏ lớn.

Tôi có thể viết một số JS để tải các dữ liệu attrs vào HTML được tạo ra, nhưng sau đó tôi phải tạo JS tùy chỉnh dựa trên dữ liệu Rails của tôi, và cảm thấy như cách sai để làm điều đó.

Trả lời

7

Tôi nghĩ bạn có thể làm điều đó như thế này:

= f.input :parts do 
    = f.collection_check_boxes :parts, @parts_list, :id, :to_s, item_wrapper_tag: :label, item_wrapper_class: :checkbox do |b| 
    - b.check_box(data: { YOUR DATA ATTRIBUTES HERE }) + b.text 
+0

Nhưng làm thế nào bạn có thể làm điều này tự động? không có biến nào để ràng buộc chống lại… – andrewdotnich

+1

b.object là phần tử riêng lẻ của bộ sưu tập, vì vậy bạn có thể thực hiện những việc như dữ liệu: {identifier: b.object.identifier} v.v., sẽ cung cấp cho mỗi hộp kiểm trong nhóm dữ liệu của riêng nó thuộc tính (đối diện với cùng một giá trị cho tất cả chúng nếu bạn đặt nó vào input_html) –

+0

Thứ nhất, xin lỗi vì sự chậm trễ một năm rưỡi trong phản hồi! Tôi thích câu trả lời này tốt nhất vì nó rất đơn giản, mặc dù vẫn còn thêm mã Ruby & JS để viết. Tôi đã không thử nghiệm nó (từ lâu tôi đã chuyển từ cả dự án đó và chủ nhân) nhưng - giả sử nó hoạt động - việc đưa danh sách rô bốt cho mỗi phần trong phần tử dữ liệu tạo ra rất nhiều ý nghĩa và dễ dàng trận đấu với. Cảm ơn bạn! – yoz

0

Một số tùy chọn đầu vào trong SimpleForm chấp nhận một lambda đó được gọi cho tất cả các mục trong một bộ sưu tập:

f.input :role_ids, :collection => (1..10).to_a, 
    :label_method => :to_i, :value_method => :to_i, 
    :as => :check_boxes, :required=> true, 
    :disabled => ->(item){ item.even? } 

nhưng input_html không dường như là một trong số họ.

Giải pháp có thể là tạo một đầu vào bộ sưu tập SimpleForm tùy chỉnh áp dụng chính các thuộc tính dữ liệu. Không phải là linh hoạt có lẽ, nhưng tôi nghĩ rằng đây là cách duy nhất để đi cho bây giờ.

There's a tutorial page on GitHub sẽ giúp bạn bắt đầu.

9

Giả sử biểu mẫu dành cho mô hình Order và bạn đang thay đổi bộ sưu tập parts dựa trên giá trị của trường được gọi là region.

Cập nhật chế độ xem biểu mẫu. Chỉ định id cho biểu mẫu, trường region và trường parts.

= simple_form_for(@order, :html => { :id => "order-form"}) do |f| 
    = f.input :region, :wrapper_html => { :id => "order-form-region",      | 
     "data-parts-url" => parts_orders_path(:id => @order.id, :region => @order.region)} | 

    = f.input :parts, as: check_boxes, collection: @parts_list,       | 
     :wrapper_html => { id' => 'parts-check-box-list'}         | 

Thêm một hành động mới gọi là parts trong file route.rb.

resources :orders do 
    collection do 
    get :parts 
    end 
end 

Thêm hành động mới để điều khiển

class OrdersController < ApplicationController 

    # expects id and region as parameters 
    def parts 
    @order = params[:id].present? ? Order.find(params[:id]) : Order.new 
    @parts_list = Part.where(:region => params[:region]) 
    end 
end 

của bạn Thêm một helper

def parts_collection(order, parts_list) 
    "".tap do |pc| 
    # to generate the markup for collection we need a dummy form 
    simple_form_for(order) do |f| 
     pc << f.input(:parts, as: check_boxes, collection: parts_list, 
     :wrapper_html => {:id => 'parts-check-box-list'}) 
    end 
    end 
end 

Thêm một cái nhìn js cho hành động (orders/parts.js.erb)

$('#parts-check-box-list').replaceWith('<%= j(parts_collection(@order, @parts_list)) %>'); 

ký dữ liệu thay đổi sự kiện các trình xử lý cho trường region trong số application.js

$(document).ready(function() { 
    $('#order-form').on("change", "#order-form-region", function() { 
    // Access the data-parts-url set in the region field to submit JS request 
    $.getScript($(this).attr('data-parts-url')); 
    }); 
}); 
+0

Sửa lỗi trong mã. –

+0

Thứ nhất, xin lỗi vì sự chậm trễ một năm rưỡi để đáp lại! Đây là một câu trả lời hoàn chỉnh, thật tuyệt vời. Cảm ơn bạn! Cuối cùng tôi đã đi cho câu trả lời của Shuo Chen - mặc dù không hoàn toàn của nó, nó cho thấy rằng tôi có thể nhận được tất cả mọi thứ tôi cần trong trang một cách thực sự đơn giản, mà không cần sử dụng AJAX. Nhưng đối với bất cứ điều gì phức tạp hơn tình hình cụ thể của tôi, của bạn trông giống như một cách tuyệt vời để đi và tôi chắc chắn tôi sẽ cần nó cho một cái gì đó trong tương lai. Cảm ơn bạn! – yoz

1

điều này có thể đơn giản hơn.

Giả

@robots - an array containing the list of robots 
@parts - a hash containing a list of parts for each robot 

Mẫu Mã

# controller 
@robots = %w[tracker nontracker] 
@parts = { tracker: %w[wheels lcd resistor], nontracker: %w[lcd resistor] } 

# view 
= f.input :robots, as: :select, collection: @robots, input_html: { id: 'robot-select' } 

#parts-list 

:javascript 
    var parts = #{@parts.to_json}; 

    $(document).ready(function() { 
    $('#robot-select').change(function() { 
     $('#parts-list').html(''); 

     $(parts[$(this).val()]).each(function(index, text) { 
     $('#parts-list').append('<input type="checkbox" value=' + text + '>' + text + '</input>') 
     })   
    }) 
    }) 

bạn có thể thấy làm việc này nếu bạn sao chép https://github.com/jvnill/simple_form_search_app và đi đến /robots

+0

Thứ nhất, xin lỗi vì sự chậm trễ một năm rưỡi để đáp lại! Tôi yêu mã đơn giản như thế nào cho cái này, nó rất nhỏ. Điều duy nhất tôi không thích là nó xây dựng một phần của hình thức ở phía khách hàng, và tôi vẫn cần phải cung cấp cho các hộp kiểm tên đúng cho các bộ phận. Nhưng cảm ơn bạn! – yoz