gregbast1994
gregbast1994

Reputation: 477

Woocommerce change product variation via JS

Here's a working example of where we are: http://fpusa.drunk.kiwi/product/ship-your-idea-2/

I am trying to create 'swatches' for a user to click, which would than change the value of the hidden select box woocommerce uses to grab the variation data.

Is there a specific way to tell woocommerce to read the value of the select box?

Everything works as expected but the javascript event which changes the variation id and gets everything ready to add to cart never happens.

Note: I hide the wc_dropdown with d-none because I thought it would minimize a custom solution.

Variable.php - Calls fpusa_product_attribute_button();

<?php foreach ( $attributes as $attribute_name => $options ) : ?>

  <tr class="">
    <td class="label"><label for="<?php echo esc_attr( sanitize_title( $attribute_name ) ); ?>"><?php echo wc_attribute_label( $attribute_name ); // WPCS: XSS ok. ?></label></td>
        <td class="value">
            <?php
              fpusa_product_attribute_button( $options, $attribute_name, $product );

              wc_dropdown_variation_attribute_options( array(
                'options'   => $options,
                'attribute' => $attribute_name,
                'product'   => $product,
                'class'         => 'd-none',
              ));

            echo end( $attribute_keys ) === $attribute_name ? wp_kses_post( apply_filters( 'woocommerce_reset_variations_link', '<a class="reset_variations" href="#">' . esc_html__( 'Clear', 'woocommerce' ) . '</a>' ) ) : '';

            ?>
        </td>
    </tr>

<?php endforeach; ?>

fpusa_product_attribute_button()

function fpusa_product_attribute_button( $options, $attribute_name, $product ){
    if( ! empty( $options ) ) : ?>
        <div id="var_btn" class="d-flex">
            <?php foreach( $options as $option ): ?>
                <button type="button" class="d-flex btn justify-content-center align-items-center border mx-1" data-key="<?php echo $attribute_name ?>" data-value="<? echo $option ?>">
                    <?php echo $option; ?>
                </button>
            <?php endforeach; ?>
        </div> <?php
    endif;
}

Functions.js

$('#var_btn button').click(function(){
   let attribute = $(this).attr('data-key');
   let option = $(this).attr('data-value');
   console.log( attribute, option );
   $('#' + attribute).val( option );
});

Upvotes: 6

Views: 5235

Answers (2)

Maks Devda
Maks Devda

Reputation: 101

Modify function to use name not slug in button text:

function fpusa_product_attribute_button( $options, $attribute_name, $product ){
if( ! empty( $options ) ) :
    
    if ( $product && taxonomy_exists( $attribute_name ) ) {
        // Get terms if this is a taxonomy - ordered. We need the names too.
        $terms = wc_get_product_terms(
            $product->get_id(),
            $attribute_name,
            array(
                'fields' => 'all',
            )
        );
        foreach ( $terms as $term ) {
            if ( in_array( $term->slug, $options, true ) ) {
                $html .= '<button data-value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name, $term, $attribute, $product ) ) . '</button>';
            }
        }
    } else {
        foreach ( $options as $option ) {
            // This handles < 2.4.0 bw compatibility where text attributes were not sanitized.
            $selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false );
            $html    .= '<button data-value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option, null, $attribute, $product ) ) . '</button>';
        }
    }

    ?>
    <div id="var_btn" class="d-flex">
        <?php echo $html; ?>
    </div> <?php
endif;

}

Upvotes: 0

gregbast1994
gregbast1994

Reputation: 477

All I had to do is simply trigger the change event on the <select> was passing the selected option to.

$('#var_btn button').click(function(){
    let attribute = $(this).attr('data-key');
    let option = $(this).attr('data-value');
    console.log( attribute, option );
    $('#' + attribute).val( option ).change();
  });

Upvotes: 4

Related Questions