Spree下拉框用于变体选项值

时间:2016-01-20 11:18:07

标签: ruby-on-rails ruby-on-rails-4 spree form-for

我正在学习Spree 3.0,我设置了一个卖短裤的测试店。

Shorts有多种选项类型:尺寸,颜色,长度

我想改变它从前端复选框到下拉框显示前端变体选项的方式。

目前,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

我想知道将选项值拆分为单个下拉菜单的最佳方法吗?

我非常感谢任何帮助,谢谢。

3 个答案:

答案 0 :(得分:5)

这并不像看起来那么容易,因为您将使用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_stockbackorderable还是track_inventory?false并回复错误或更新的购物车:)

我希望这有帮助

答案 1 :(得分:1)

这就是我为解决这个问题所做的。它基本上采用由单选按钮控制的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>

答案 2 :(得分:0)

您如何更新/更新产品图片(例如Ruby on Rails棒球服)  例如)我选择了这两个,我想显示蓝色的一个

这是我对js.erb文件所做的操作(我在那里解决了):

// Update hidden field #varient_id's value. 
$('#variant_id').val('<%= @variant.id %>')
// Render product/_image partial
$('#main-image').html("<% j (render partial: 'image', locals: 
{product: @variant}) %>");
// Update price
$('.price.selling').html('<%= number_to_currency @variant.price %>');
<% if @variant.in_stock? && @variant.available_on %> 
    // 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 %>

但是它不起作用,请帮助