2016-01-20 62 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>