Home > Net >  How to make Woocommerce Upsells and Cross-Sells manually sortable
How to make Woocommerce Upsells and Cross-Sells manually sortable

Time:01-13

This seems so simple, but I'm stuck. Hoping someone can help.

I'm trying to make the cross-sell and upsell select2 boxes sortable on the edit product page, and as I was testing it in console it did add the sorting handles, but when saving the product, it reverted to alphabetical order.

$("ul.select2-selection__rendered").sortable({
      containment: 'parent'
});

On front end, I believe I could achieve manual order by just using the sorting filter as 'none'

add_filter( 'woocommerce_upsells_orderby', 'filter_woocommerce_upsells_orderby', 10, 1 );

function filter_woocommerce_upsells_orderby( $orderby ){
    return "none";
};

But how to best achieve manual ordering on the edit product page (and on front end)? Surely there must be an easier way to enable sorting.

Any help would be appreciated, thanks.

CodePudding user response:

You could store the order of the products in a custom meta field, and then use that field to sort the products when they are displayed.

In the save_post action, get the current order of the products from the sortable list.

Save this order as a meta field for the product post. Use the meta field to order the products in the woocommerce_upsell_display and woocommerce_cross_sell_display actions.

CodePudding user response:

Managed to figure it out in the end. It was just an incomplete js issue. I wasn't properly setting up the 'sortable' property for the fields. After I did, the order was saved properly.

jQuery(document).ready(function ($) {
        
    $( 'select.wc-product-search.enhanced' ).each( function() {
        
        //Add sortable attribute to select2 product fields (upsell and cross-sell)
        $(this).attr('data-sortable', true);
        
        let $select = $(this);
        let $list   = $(this).next( '.select2-container' ).find( 'ul.select2-selection__rendered' );
        
        $list.sortable({
            placeholder : 'ui-state-highlight select2-selection__choice',
            forcePlaceholderSize: true,
            items       : 'li:not(.select2-search__field)',
            tolerance   : 'pointer',
            stop: function() {
                $( $list.find( '.select2-selection__choice' ).get().reverse() ).each( function() {
                    var id     = $( this ).data( 'data' ).id;
                    var option = $select.find( 'option[value="'   id   '"]' )[0];
                    $select.prepend( option );
                } );
            }
        });
    
    });
    
});

And like said above, on the front-end to make sorting respect the saved order from the field, I set orderby property to 'none'

  • Related