WooCommerce变奏曲作为单选按钮



在WooCommerce中,是否可以在不使用插件的情况下将变体下拉列表更改为单选按钮?我想在变体部分有以下设置:

  • 1升(10欧元)
  • 2升(20欧元)
  • 3升(25欧元)

当您选择一个选项时,底部的价格应该会自动更改。

EDIT:由于@ThomasB,添加了variation_check()和JS变体检查!

EDIT2:确保variation_check()也检查延期订单状态,以便选择何时可以延期订购产品。

我设法做到这一点的最好方法是在选择下拉列表之后直接添加单选按钮标记,然后使用CSS隐藏选择下拉列表。您还需要一些自定义JS来触发隐藏的选择值更改,这样您的价格就会根据您选择的单选按钮而更改。

以下是我添加标记的方式:

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);

这是我使用的JS:

$(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);
    }
  });
});

如果没有插件,我不知道如何做到这一点,但我建议您放弃这一要求,使用Wooccommerce Radio Buttons插件。这正是您想要的:

您可以使用Variation Swatches for WooCommerce插件。它对我有效。

我进一步扩展了cfx答案的JavaScript部分,以包括多种变体的情况。其想法是根据选择输入隐藏和显示可用的变体(单选按钮)。

<script>
    jQuery(document).on('change', '.variation-radios input', function() {
      jQuery('.variation-radios input:checked').each(function(index, element) {
        let el = jQuery(element);
        jQuery('select[name="' + el.attr('name') + '"]').val(el.attr('value')).trigger('change');
        recreateRadioInputs();
      });
    });
    
    jQuery(document).on('woocommerce_update_variation_values', function() {
      jQuery('.variation-radios input').each(function(index, element) {
        let el = jQuery(element);
        el.removeAttr('disabled');
        if(jQuery('select[name="' + el.attr('name') + '"] option[value="' + el.attr('value') + '"]').is(':disabled')) {
          $el.prop('disabled', true);
        }
      });
    });
    
    // recreate readio inputs based on the select inputs
    function recreateRadioInputs() {
        jQuery('.variation-radios input, .variation-radios label').hide();
        jQuery('.variations select').each(function() {
            let inputName = jQuery(this).attr('name');
            jQuery(this).find('option').each(function() {
                let inputVal = jQuery(this).val();
                let radioInput = jQuery('.variation-radios input[value="' + inputVal + '"]');
                jQuery('.variation-radios label[for="' + radioInput.attr('id') + '"]').show();
                radioInput.show();
            });
        });
    }
</script>

最新更新