2016-01-20 61 views
5

我正在學習Spree 3.0,並且我已經設置了一家銷售短褲的測試店。Spree下拉框的變體選項值

短褲有多個選項類型:尺寸,顏色,長度

我想改變它顯示從無線電覆選框前端的形式選項的下拉框的方式。

目前,施普雷顯示選項類型爲單選按鈕:

Current Spree setup

我想改變這種使用下拉菜單爲每個選項類型,像這樣:

What I want Spree to do

我試過以下內容:

<%= select_tag "variant_id", options_for_select(@product.variants_and_option_values(current_currency).collect{ |v| ["#{variant_options(v)} #{variant_price(v)}", v.id] })%> 

但它只是顯示所有選項類型的值在每個標籤:

Dropdown with all the option types 1

Dropdown with all the option types 2

我想知道分裂選項值成單獨的下拉菜單中選擇最好的方法是什麼?

任何幫助,我非常感謝,謝謝。

回答

4

這不像看起來那麼容易,因爲您將使用Spree::OptionValue記錄而不是變體,並且在某些時候您需要將其轉換回變體以將其添加到您的購物車。組合可能不可能和/或缺貨,所以使用option_values是非常不切實際的。

但無論如何,你想知道我怎麼這麼設置如下:

@options = Spree::OptionValue.joins(:option_value_variants).where(spree_option_value_variants: { variant_id: @product.variant_ids }).group_by(&:option_type) 

這會給你與哈希作爲密鑰的哈希option_types(大小,顏色,你的情況長度)並且這些值是option_values的數組。

你可以很容易形成這種成收音機這樣的:

<% @options.each do |option_type, option_values| %> 
    <%= content_tag :h2, option_type.presentation %> 
    <% option_values.each do |option_value| %> 
    <%= radio_button_tag option_type.name, option_value.id %> 
    <%= label_tag option_value.presentation %> 
    <% end %> 
<% end %> 

或爲下拉菜單:

<% @options.each do |option_type, option_values| %> 
    <%= content_tag :h2, option_type.presentation %> 
    <%= collection_select :variants, option_type.name, option_values, :id, :presentation %> 
<% end %> 

而在你的控制,你會希望找到一個變種符合這3個條件,檢查是否它是in_stock,backorderabletrack_inventory?false和迴應有錯誤或更新的購物車:)

我希望這有助於

+0

感謝迴應Fabian。看起來很困難。我正在專門查看下拉框。也許,一個Javascript解決方案可能是答案,隱藏無線電。 –

+0

無線電的可以很容易地轉換爲選擇。它是同一種東西,從上下文中的一組選項中選擇一個選項。我之前在SPA中實現過這一點,我使用api從一個產品中獲取所有變體,然後獲取其中'in_stock:true'我收集選項值並僅向用戶顯示這些option_values的變體。或者,也許灰色的股票變種的選項 –

+0

再次感謝@Fabian de Pabian,我需要消化這個並找出如何實現它。我可以簡單地將收音機轉換爲下拉菜單,但每個產品的選項類型只需一個下拉菜單,而不是單獨的顏色下拉菜單;尺寸; –

0

這就是我所做的解決這個問題。它基本上採用由單選按鈕控制的variant_id參數,並將其變爲由jQuery和AJAX控制的隱藏字段,並帶有其他通知。

我希望這可以幫助別人。

配置/ routes.rb中

# Mount the core routes 
Rails.application.routes.draw do 
    mount Spree::Core::Engine, at: '/' 
end 

# Create new routes 
Spree::Core::Engine.routes.draw do 
    post "products/:product_id/get_variant", 
     to: "products#toggle_like", 
     as: "get_variant", 
     constraints: { :format => /(js)/ } 
end 

應用/模型/禮包/ product_decorator.rb

Spree::Product.class_eval do 

    # Find the Product's Variant from an array of OptionValue ids 
    def find_variant_by_options(array) 
    option_values = Spree::OptionValue.where(id: array) 
    variants = [] 
    option_values.each do |option_value| 
     variants.push(option_value.variants.ids) 
    end 
    self.variants.find_by(:id => variants.inject(:&).first) 
    end 
end 

應用程序/控制器/禮包/ products_controller_decorator.rb

Spree::ProductsController.class_eval do 

    # Get the Variant from params[:ids], respond with JavaScript 
    def get_variant 
    @product = Spree::Product.find_by :slug => params[:product_id] 
    @variant = @product.find_variant_by_options(params[:ids].split(',')) 

    respond_to do |format| 
     format.js 
    end 
    end 
end 

應用程序/視圖/大禮包/產品/ get_variant.js.erb

// Update hidden field #varient_id's value. 
$("#variant_id").val("<%= @variant.id %>") 
// Update price 
$(".price.selling").html("<%= number_to_currency @variant.price %>"); 
<% if @variant.in_stock? && @variant.available? %> 
// If in stock and available 
    $("#add-to-cart-button").prop("disabled", false); // Enable button 
    $(".out-of-stock").hide(); // Hide 'out of stock' message 
<% else %> 
// Otherwise 
    $("#add-to-cart-button").prop("disabled", true); // Disable button 
    $(".out-of-stock").show(); // Show 'out of stock' message 
<% end %> 

應用程序/視圖/大禮包/產品/ _cart_form.html.erb

<%= form_for order, url: populates_orders_path do |f| %> 
    ... 
    <% if @product.variants_and_option_values(current_currency).any? %> 
    <div id="product_variants" class="col-md-6"> 
     <h3 class="product-section-title"><%= Spree.t(:variants) %></h3> 
     <% @product.option_types.each do |option_type| %> 
     <%= f.label "option_type_#{option_type.id}", option_type.name %> 
     <br> 
     <%= f.select "option_type_value_#{option_type.id}", 
        option_type.option_values.all.collect { |v| [ v.name, v.id ] }, 
        { include_blank: true }, 
        { class: "form-control" } %> 
     <br> 
     <% end %> 
     <%= hidden_field_tag "variant_id", value: "0" %> 
     ... 
    </div> 
    <% else %> 
    <%= hidden_field_tag "variant_id", @product.master.id %> 
    <% end %> 
    ... 
    <span class="price selling" 
      itemprop="price" 
      content="<%= @product.price_in(current_currency).amount.to_d %>"> 
     <%= display_price(@product) %> 
    </span> 
    ... 
    <%= button_tag class: "btn btn-success", 
         id: "add-to-cart-button", 
       disabled: @product.variants.any?, 
        type: :submit do %> 
     <%= Spree.t(:add_to_cart) %> 
    <% end %> 
    ... 
    <span class="out-of-stock" style="display: none;"> 
    <%= Spree.(:out_of_stock) %> 
    </span> 
<% end %> 

<script> 
    // Call AJAX if all options are selected, otherwise clean up. 
    $("#product-variants select").change(function(){ 
    var option_value_ids = []; 
    $("#product-variants select").each(function(){ 
     option_value_ids.push($(this).val()); 
    }); 
    if(option_value_ids.indexOf("") == -1){ 
     $.ajax({ 
     url: "<%= get_variant_path(@product) %>?ids=" + option_value_ids.join(','), 
     method: "post" 
     }); 
    }else{ 
     $("#variant_id").val("0"); 
     $("#add-to-cart-button").prop("disabled", true); 
     $(".out-of-stock").hide(); 
    } 
    }); 
</script>