Dies ist, was ich getan habe, um dieses Problem zu lösen. Es nimmt im Grunde genommen den variant_id
Parameter, der durch die Radioknöpfe kontrolliert wurde und verwandelt es in ein verstecktes Feld, das durch jQuery und AJAX mit zusätzlichen Mitteilungen gesteuert wird.
Ich hoffe, das hilft jemandem.
config/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
app/Modelle/spree/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
app/Controller/Spree/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
app/views/Spree/products/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 %>
app/views/Spree/products/_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>
Vielen Dank für die Antwort Fabian. Es sieht schwierig aus. Ich habe speziell Dropdown-Boxen angeschaut. Vielleicht könnte eine Javascript-Lösung die Antwort sein und die Radios verstecken. –
Radios können leicht in eine Auswahl konvertiert werden. Es ist die gleiche Art von Sache, wählen Sie eine Option aus einer Reihe von Optionen in einem Kontext. Ich habe dies zuvor in einem SPA implementiert und ich habe die API verwendet, um alle Varianten von einem Produkt zu bekommen, und dann für die Varianten, bei denen "in_stock: true" die Optionswerte gesammelt und dem Benutzer nur diese Optionswerte angezeigt hat. Oder vielleicht die Optionen für vergriffene Varianten ausgrauen –
Nochmals vielen Dank @Fabian de Pabian, ich muss dies verdauen und herausfinden, wie man es implementiert. Ich kann das Radio einfach in das Dropdown-Menü umwandeln, aber es gibt Optionstypen pro Produkt in einem Dropdown-Menü, anstatt eines Dropdown-Menüs für die Farbe. Größe; etc .. –