我正在学习Spree 3.0,我设置了一个卖短裤的测试店。
Shorts有多种选项类型:尺寸,颜色,长度
我想改变它从前端复选框到下拉框显示前端变体选项的方式。
目前,Spree将选项类型显示为单选按钮:
我想更改此选项以使用每种选项类型的下拉菜单,如下所示:
我尝试了以下内容:
<%= select_tag "variant_id", options_for_select(@product.variants_and_option_values(current_currency).collect{ |v| ["#{variant_options(v)} #{variant_price(v)}", v.id] })%>
但它只是显示每个标签中所有选项类型的值:
我想知道将选项值拆分为单个下拉菜单的最佳方法吗?
我非常感谢任何帮助,谢谢。
答案 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_stock
,backorderable
还是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 %>
但是它不起作用,请帮助