Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WooCommerce Variations as Radio Buttons

is it possible within WooCommerce to change the variations dropdown into radio buttons without having to work with a plugin? I would like to have the following setup on the variations section:

  • 1 liter (10€)
  • 2 liter (20€)
  • 3 Liter (25€)

The price at the bottom should be automatically changed when you select an option.

Thank you

like image 254
Sam De Decker Avatar asked Mar 25 '16 12:03

Sam De Decker


People also ask

What is a radio button in WooCommerce?

Description. Variations Radio Buttons and Swatches is highly customizable plugin that lets you choose a color and an image for each attribute term, orientation of the options, different positions of the attribute label as well as to display thumbnail and price before or after the option's name.

How do I create a custom variation in WooCommerce?

To add our variation-specific custom fields, go to the Product Add-Ons tab in the Product data section. Click 'Add Group' then 'Add Field'. In the 'Field Type' setting, choose 'Information'. In the screenshot above, you can see the Product Add-Ons panel.


2 Answers

EDIT: added variation_check() and JS variation checking thanks to @ThomasB!

EDIT2: make sure variation_check() also checks for backorder status to allow selection when a product can be backordered.

The best way I managed to get this working is to add radio button markup directly after the select dropdowns and then hide the select dropdowns using CSS. You'll also need some custom JS to trigger the hidden select value changes so that your price will change according to the radio button you select.

Here's how I added the markup:

function variation_radio_buttons($html, $args) {
  $args = wp_parse_args(apply_filters('woocommerce_dropdown_variation_attribute_options_args', $args), array(
    'options'          => false,
    'attribute'        => false,
    'product'          => false,
    'selected'         => false,
    'name'             => '',
    'id'               => '',
    'class'            => '',
    'show_option_none' => __('Choose an option', 'woocommerce'),
  ));

  if(false === $args['selected'] && $args['attribute'] && $args['product'] instanceof WC_Product) {
    $selected_key     = 'attribute_'.sanitize_title($args['attribute']);
    $args['selected'] = isset($_REQUEST[$selected_key]) ? wc_clean(wp_unslash($_REQUEST[$selected_key])) : $args['product']->get_variation_default_attribute($args['attribute']);
  }

  $options               = $args['options'];
  $product               = $args['product'];
  $attribute             = $args['attribute'];
  $name                  = $args['name'] ? $args['name'] : 'attribute_'.sanitize_title($attribute);
  $id                    = $args['id'] ? $args['id'] : sanitize_title($attribute);
  $class                 = $args['class'];
  $show_option_none      = (bool)$args['show_option_none'];
  $show_option_none_text = $args['show_option_none'] ? $args['show_option_none'] : __('Choose an option', 'woocommerce');

  if(empty($options) && !empty($product) && !empty($attribute)) {
    $attributes = $product->get_variation_attributes();
    $options    = $attributes[$attribute];
  }

  $radios = '<div class="variation-radios">';

  if(!empty($options)) {
    if($product && taxonomy_exists($attribute)) {
      $terms = wc_get_product_terms($product->get_id(), $attribute, array(
        'fields' => 'all',
      ));

      foreach($terms as $term) {
        if(in_array($term->slug, $options, true)) {
          $id = $name.'-'.$term->slug;
          $radios .= '<input type="radio" id="'.esc_attr($id).'" name="'.esc_attr($name).'" value="'.esc_attr($term->slug).'" '.checked(sanitize_title($args['selected']), $term->slug, false).'><label for="'.esc_attr($id).'">'.esc_html(apply_filters('woocommerce_variation_option_name', $term->name)).'</label>';
        }
      }
    } else {
      foreach($options as $option) {
        $id = $name.'-'.$option;
        $checked    = sanitize_title($args['selected']) === $args['selected'] ? checked($args['selected'], sanitize_title($option), false) : checked($args['selected'], $option, false);
        $radios    .= '<input type="radio" id="'.esc_attr($id).'" name="'.esc_attr($name).'" value="'.esc_attr($option).'" id="'.sanitize_title($option).'" '.$checked.'><label for="'.esc_attr($id).'">'.esc_html(apply_filters('woocommerce_variation_option_name', $option)).'</label>';
      }
    }
  }

  $radios .= '</div>';
    
  return $html.$radios;
}
add_filter('woocommerce_dropdown_variation_attribute_options_html', 'variation_radio_buttons', 20, 2);

function variation_check($active, $variation) {
  if(!$variation->is_in_stock() && !$variation->backorders_allowed()) {
    return false;
  }
  return $active;
}
add_filter('woocommerce_variation_is_active', 'variation_check', 10, 2);

And here's the JS I used:

$(document).on('change', '.variation-radios input', function() {
  $('.variation-radios input:checked').each(function(index, element) {
    var $el = $(element);
    var thisName = $el.attr('name');
    var thisVal  = $el.attr('value');
    $('select[name="'+thisName+'"]').val(thisVal).trigger('change');
  });
});
$(document).on('woocommerce_update_variation_values', function() {
  $('.variation-radios input').each(function(index, element) {
    var $el = $(element);
    var thisName = $el.attr('name');
    var thisVal  = $el.attr('value');
    $el.removeAttr('disabled');
    if($('select[name="'+thisName+'"] option[value="'+thisVal+'"]').is(':disabled')) {
      $el.prop('disabled', true);
    }
  });
});
like image 166
cfx Avatar answered Oct 07 '22 15:10

cfx


I don't know how to do that without a plugin, but I suggest you drop that requirement, and use the Woocommerce Radio Buttons plugin. This does exactly what you want:

like image 32
Sajid anwar Avatar answered Oct 07 '22 13:10

Sajid anwar