Force WooCommerce to update fragment

20,784

Solution 1

After hours of digging if finaly figured out, why this is happening.

First things first: Woocommerce saves content of the fragments into sessionStorage inside of browser and doesn't update it until a new product is inserted into cart. On the other hand, the sessionStorage is monitored for changes so fragments are updated at all tabs (if there are any) at the same time.

Based on this, I created easy solution which refreshes fragments after page reload and then it updates fragments every minute.

The javascript needed for reloading:

jQuery( function ($) {
    var cart_hash_key = substitutions.cart_hash_key;

    function refresh_fragments() {
        // Better to put there 'blank' string then empty string
        window.sessionStorage.setItem(cart_hash_key, 'blank'); 
        var e = $.Event("storage");

        e.originalEvent = {
            key: cart_hash_key,
        };

        $(window).trigger(e);
    }

    refresh_fragments();
    setInterval(refresh_fragments, 60000);
});

Last bit is inserting the script into page with correct substitutions:

function register_load_fragments_script() {
    // Register the script
    wp_register_script( 'load-fragments-script', get_template_directory_uri() . '/js/load-fragments.js', array(), '20170121', true  );

    // Substitustions in script
    $translation_array = array(
        'cart_hash_key' => WC()->ajax_url() . '-wc_cart_hash'
    );
    wp_localize_script( 'load-fragments-script', 'substitutions', $translation_array );

    wp_enqueue_script( 'load-fragments-script' );
}

I hope this will help someone not to spend whole day trying to solve it ;-)

Solution 2

There is probably a shorter answer by triggering a core handler found in Woocommerce to refresh fragments via ajax.

function refresh_fragments() {
    console.log('fragments refreshed!');
    $( document.body ).trigger( 'wc_fragment_refresh' );
}

refresh_fragments();
setInterval(refresh_fragments, 60000);

This code should trigger the following function binded to 'wc_fragment_refresh' found in cart-fragments.js

function refresh_cart_fragment() {
    $.ajax( $fragment_refresh );
}

Solution 3

In my case, I just wanted to refresh the cart once for all my users since I had made a significant change to how the cart items are displayed. Going with a script would require me to remove it after some time (when I think most of my users have had their carts refreshed). I found clearing all existing Woocommerce Sessions by going to Woocommerce -> Tools and clicking Clear under Clear customer sessions to be better suited for my use case.

Share:
20,784
Jan Herzán
Author by

Jan Herzán

Languages: Java C# Javascript (HTML5, CSS3)

Updated on January 13, 2021

Comments

  • Jan Herzán
    Jan Herzán almost 3 years

    I created plugin which uses WooCommerce fragments for showing to user how many points they have. When user uses some of the points (by adding product into cart) everything works ok.

    But when admin adds points to user by admin-interface, the fragment is not updated until user adds a new product into cart.

    Here is code sample:

    function create_points_widget_content() {
        $usersPoints = esc_attr( get_user_meta( get_current_user_id(), USERS_POINTS, true ));
        if (!isset($userPoints) || $userPoints == "") $userPoints = 0;
        $usedPoints = get_current_points_in_cart('', 0);
    
        ?>
            <div class="points-widget-v2">
                <div><?php echo __("Your points", "plugin-domain"); ?>:<span class="users-points"><?php echo $usersPoints; ?></span></div>
                <div><?php echo __("Actually used", "plugin-domain"); ?>:<span class="used-points"><?php echo $usedPoints; ?></span></div>
            </div>
        <?php
    }
    
    // Update top right price
    function add_points_widget_to_fragment( $fragments ) {
        global $woocommerce;
        ob_start();
    
        create_points_widget_content();
    
        $fragments['div.points-widget-v2'] = ob_get_clean();
        return $fragments;
    }
    add_filter('add_to_cart_fragments', 'add_points_widget_to_fragment');
    

    Is there any way how to force fragments to refresh itself?

  • koceeng
    koceeng over 6 years
    Thanks a lot for the answer, however please add more description and/or information and how it solves the asked problem so others can easily understand it without asking for clarification :)
  • efoula
    efoula about 6 years
    You're the best. Thank u so much.
  • Ziki
    Ziki over 4 years
    Thanks for pointing out that cart fragments are stored in session and update on cart item add/remove. I modified the mini-cart template and couldn't understand why my changes don't reflect on frontend. Turns out I just need to remove a product.
  • Aleksandr Abramov
    Aleksandr Abramov almost 2 years
    Save my day! Thanks!
  • Steve Moretz
    Steve Moretz almost 2 years
    Not working anymore as it seems.