这就是我所做的解决这个问题。它基本上采用由单选按钮控制的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>
感谢回应Fabian。看起来很困难。我正在专门查看下拉框。也许,一个Javascript解决方案可能是答案,隐藏无线电。 –
无线电的可以很容易地转换为选择。它是同一种东西,从上下文中的一组选项中选择一个选项。我之前在SPA中实现过这一点,我使用api从一个产品中获取所有变体,然后获取其中'in_stock:true'我收集选项值并仅向用户显示这些option_values的变体。或者,也许灰色的股票变种的选项 –
再次感谢@Fabian de Pabian,我需要消化这个并找出如何实现它。我可以简单地将收音机转换为下拉菜单,但每个产品的选项类型只需一个下拉菜单,而不是单独的颜色下拉菜单;尺寸; –