2016-01-20 15 views
5

Uczę się Spree 3.0 i mam konfigurację sklepu testowego, który sprzedaje szorty.Spree listy rozwijane dla wariantów wartości opcji

Spodenki ma wiele typów opcji: rozmiar, kolor, długość

Chciałem zmienić sposób wyświetla opcje wariant nakładka z pole wyboru radiowej do listy rozwijanej.

Obecnie Spree wyświetla typy opcji jak przyciski radia:

Current Spree setup

chcę to zmienić, aby korzystać z rozwijanego menu dla każdego typu opcji, na przykład:

What I want Spree to do

Próbowałem następujące:

<%= select_tag "variant_id", options_for_select(@product.variants_and_option_values(current_currency).collect{ |v| ["#{variant_options(v)} #{variant_price(v)}", v.id] })%> 

Ale to po prostu wyświetla wartości wszystkich typów opcji w każdym tagu:

Dropdown with all the option types 1

Dropdown with all the option types 2

Chciałem wiedzieć, że najlepszym sposobem, aby podzielić wartości opcji na poszczególne menu rozwijanych?

Każda pomoc jest dla mnie bardzo cenna, dziękuję.

Odpowiedz

4

To nie jest takie proste, jak się wydaje, ponieważ będziesz używać rekordów Spree::OptionValue zamiast wariantów iw pewnym momencie będziesz chciał przekonwertować z powrotem na warianty, aby dodać je do koszyka. Kombinacje mogą nie być możliwe i/lub niedostępne w magazynie, więc praca z wartościami opcji jest wysoce niepraktyczna.

Ale mimo wszystko, chcesz wiedzieć, jak więc skonfigurować następujące:

@options = Spree::OptionValue.joins(:option_value_variants).where(spree_option_value_variants: { variant_id: @product.variant_ids }).group_by(&:option_type) 

To daje hash z klawiszy mieszania będących option_types (rozmiar, kolor, długość w danym przypadku) oraz wartości będące tablicami wartości opcji.

Można łatwo tworzyć to do radia tak:

<% @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 %> 

Or dla rozwijanego menu:

<% @options.each do |option_type, option_values| %> 
    <%= content_tag :h2, option_type.presentation %> 
    <%= collection_select :variants, option_type.name, option_values, :id, :presentation %> 
<% end %> 

A w kontrolerze, co chcesz znaleźć wariant dopasowanie te 3 kryteria, należy sprawdzić, czy to jest in_stock, backorderable lub track_inventory? jest false i odpowiada błędami lub zaktualizowanym koszykiem :)

Mam nadzieję, że pomogło to

+0

Dzięki za odpowiedź Fabian. To wygląda na trudne. Właśnie patrzyłem na skrzynie rozwijane. Być może rozwiązaniem jest JavaScript, ukrywanie radia. –

+0

Radio można łatwo przekonwertować na wybrane. jest to ten sam rodzaj, wybierz jedną opcję z szeregu opcji w kontekście. Zaimplementowałem to wcześniej w SPA i użyłem api, aby uzyskać wszystkie warianty produktu, a następnie dla wariantów, w których 'in_stock: true' zebrałem wartości opcji i wyświetlam tylko wartości option_values ​​użytkownikowi. A może wyszarzyć opcje niedostępnych wariantów czasowych –

+0

Jeszcze raz dziękuję @Fabian de Pabian, muszę to przetrawić i dowiedzieć się, jak to zaimplementować. Mogę po prostu przekształcić radio na rozwijane, ale ma opcje typów na produkt na jednym liście rozwijanej, zamiast oddzielnego rozwijania dla koloru; rozmiar; itd .. –

0

Oto, co zrobiłem, aby rozwiązać ten problem. Zasadniczo przyjmuje on parametr variant_id kontrolowany przez przyciski opcji i zmienia go w ukryte pole kontrolowane przez jQuery i AJAX z dodatkowymi powiadomieniami.

Mam nadzieję, że to pomoże komuś.

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/models/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/controllers/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/produkty/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> 
Powiązane problemy