WooCommerce Fragment Update total items / subtotal / total - ajax

I am usign Ajax to add items to my cart, and trying to use the below code to update the WooCommerce fragments so that the item count, subtotal and total stay in sync (without page refresh). However, The below is not working, apart from the contents count, but even this is very intermittent.
Am I missing something?
function ajaxify_fragments( $fragments ) {
// Update cart count fragment
$fragments['.cart-items-total td'] = WC()->cart->get_cart_contents_count();
// Update cart subtotal fragment
$fragments['.cart-total td'] = WC()->cart->get_cart_subtotal();
// Update cart total fragment
$fragments['.cart-total td'] = WC()->cart->get_cart_total();
return $fragments;
}
add_filter( 'woocommerce_add_to_cart_fragments', 'ajaxify_fragments', 10, 1 );

After some further research, I have got this to work by separating out each fragment update into its own function. Also, using ob_start() and ob_get_clean():
function ajaxify_cart_count_fragments( $fragments ) {
// Turn on output buffering
ob_start();
// Content
echo '<td data-title="Items">' . WC()->cart->get_cart_contents_count() . '</td>';
// Update fragment with new content
$fragments['.cart-items-total td'] = ob_get_clean();
return $fragments;
}
add_filter( 'woocommerce_add_to_cart_fragments', 'ajaxify_cart_count_fragments', 10, 1 );
function ajaxify_subtotal_fragments( $fragments ) {
// Content
echo '<td data-title="Subtotal">' . WC()->cart->get_cart_subtotal() . '</td>';
// Update fragment with new content
$fragments['.cart-total td'] = WC()->cart->get_cart_subtotal();
return $fragments;
}
add_filter( 'woocommerce_add_to_cart_fragments', 'ajaxify_subtotal_fragments', 10, 1 );

Related

Add notice with ajax when user select local pickup shipping method on WooCommerce cart and checkout pages

I'm making a plugin for an client, integrated with WooCommerce, and I need to add a notice, with wc_add_notice, when a local pickup shipping method is selected on cart and checkout pages.
I've tried adding a hook to woocommerce_shipping_method_chosen action, like this:
add_action("woocommerce_shipping_method_chosen", "local_pickup_notice", 10, 1);
function local_pickup_notice($chosen_method){
$woocommerce = WC();
$shipping_method = $woocommerce->session->get("chosen_shipping_methods")[0];
if($shipping_method == "local_pickup"){
wc_add_notice(__("Local pickup shipping", "myplugin"), "notice");
}
}
But, it didn't work. No notice is showing on cart or checkout page when a local pickup is selected (also when changing shipping method).
Can anyone help me with this?
-- EDIT 1 --
I've noticed that woocommerce_shipping_method_chosen isn't fired, so I change action hook to woocommerce_cart_calculate_fees. Now, the action is fired, but still not showing the message.
Also tried changing from wc_add_notice to wc_print_notice, without success.
-- EDIT 2 --
My mistake was on checking the $shipping_method, because I have two local_pickup options. This way, the string stored on $shipping_method is local_pickup:<option_id> instead of only local_pickup. So, changing the if statement to use strpos instead == makes it working.
The current result is:
add_action("woocommerce_cart_calculate_fees", "local_pickup_notice", 10, 1);
function local_pickup_notice($cart){
$woocommerce = WC();
$shipping_method = $woocommerce->session->get("chosen_shipping_methods")[0];
wc_clear_notices();
if(strpos($shipping_method, "local_pickup") !== false){
wc_add_notice(__("Local pickup shipping", "myplugin"), "notice");
}
}
Now, it's working, but ONLY when the cart/checkout page is loaded. The next challenge is to make this work on the AJAX call, to show the notice when user changes shipping method.
If someone knows how to add notice on WooCommerce ajax, please tell me
wc_add_notice should be used in hooks that allow you to handle your custom AJAX endpoints. Certainly not in the woocommerce_cart_calculate_fees hook, that hook is used for other purposes.
To add a notice when user select local pickup as shipping method, you can use:
// jQuery - Ajax script
function action_wp_footer() {
// Only cart & checkout pages
if ( is_cart() || ( is_checkout() && ! is_wc_endpoint_url() ) ) {
$js_variable = is_cart() ? 'wc_cart_params' : 'wc_checkout_params';
// jQuery Ajax code
?>
<script type="text/javascript">
jQuery(function($) {
if ( typeof <?php echo $js_variable; ?> === 'undefined' )
return false;
// Get chosen shipping method
var c_s_m = $( 'input[name^="shipping_method"]:checked' ).val();
// Function that sen the Ajax request
function sendAjaxRequest( c_s_m ) {
$.ajax({
type: 'POST',
url: <?php echo $js_variable; ?>.ajax_url,
data: {
'action': 'chosen_shipping_method',
'chosen_shipping_method_val': c_s_m
},
success: function ( result ) {
// Remove other notices
$( '.woocommerce-info' ).remove();
// Display notices cart
$( '.woocommerce-cart-form' ).before( result );
// Display notices checkout
$( 'form.checkout' ).before( result );
// console.log(result); // Uncomment for testing
}
});
}
// On ready (DOM loaded)
sendAjaxRequest( c_s_m );
// On live "change event"
$( document.body ).on( 'change', 'input[name^="shipping_method"]', function() {
sendAjaxRequest( $( this ).val() );
});
});
</script>
<?php
}
}
add_action( 'wp_footer', 'action_wp_footer', 10, 0 );
// Php Ajax
function chosen_shipping_method_handler() {
if ( isset( $_POST['chosen_shipping_method_val'] ) ) {
$shipping_method = sanitize_key( $_POST['chosen_shipping_method_val'] );
if ( strpos( $shipping_method, 'local_pickup' ) !== false ) {
// Add notice
wc_add_notice( __( 'Local pickup shipping', 'woocommerce' ), 'notice' );
}
}
// Return printed notices to jQuery response.
wc_print_notices();
// Alway at the end (to avoid server error 500)
die();
}
add_action( 'wp_ajax_chosen_shipping_method', 'chosen_shipping_method_handler' );
add_action( 'wp_ajax_nopriv_chosen_shipping_method', 'chosen_shipping_method_handler' );

AJAX update in VAT amount in the Cart and Checkout page - Woocommerce

I have a condition for adding VAT. If condition true then i need to update the VAT value (0). And My code is working well. But it needs to reload the page to know the value of updated VAT. How can i do it without reloading the page? My code is below:
add_action( 'woocommerce_checkout_update_order_review', 'cm_checkout_based_on_amount' );
function cm_checkout_based_on_amount( $post_data ) {
WC()->customer->set_is_vat_exempt( false );
parse_str( $post_data, $output );
$minimum = 160;
$county = array('GB');
$cart_tot_order = WC()->cart->total;
if ( $cart_tot_order > $minimum && in_array( WC()->customer->get_shipping_country(), $county ) ){
WC()->customer->set_is_vat_exempt( true );
}
}
Any help will be highly appreciated. Thanks.
You can either trigger a checkout/cart update with jQuery after these details are updated, or send custom data with the order review fragments.
To update cart/checkout trigger these:
// For checkout
$(document.body).trigger('update_checkout', { update_shipping_method: false });
// For cart
$(document.body).trigger('wc_update_cart');
To send custom fragments
add_filter('woocommerce_update_order_review_fragments', 'custom_wc_fragments');
function custom_wc_fragments($fragments)
{
ob_start();
echo 'Updated content here';
$updated_content = ob_get_clean();
$selector_of_the_element_you_want_to_update = '#order_review';
$fragments[$selector_of_the_element_you_want_to_update] = $updated_content;
return $fragments;
}
Note: these codes will not work out of the box, but they are a start to how you'll approach this.

Woocommerce - Enable AJAX add to cart buttons only on specific page

On my Woocommerce shop settings I have checked the option:
[✓] Redirect to the cart page after successful addition.
And that's good behaviour for 99% of my shop.
On 1 single page (custom page with custom template) I need to enable Ajax functionality though.
Is there a way to accomplish this task in functions.php?
Ok insert this code into your functions.php. You have to replace the variable $your_ajax_page_slug with the name of your page that you want the redirect to cart functionality to be disabled. Ensure that you have 'Enable AJAX add to cart buttons on archives" checked in settings.
add_filter( 'woocommerce_get_script_data', 'modify_woocommerce_get_script_data', 20, 2 );
function modify_woocommerce_get_script_data ( $params, $handle ) {
global $wp;
$page_slug = '';
$your_ajax_page_slug = 'your-page-slug';
$current_url = home_url( $wp->request );
// Break the URL by the delimiter
$url_pieces = explode('/', $current_url);
// Get the page slug
if( is_array( $url_pieces ) )
$page_slug = end( $url_pieces );
if( $handle == 'wc-add-to-cart' && $page_slug == $your_ajax_page_slug ) {
$params['cart_redirect_after_add'] = false;
}
return $params;
}

Product Quantity in woocommerce widget Cart

I want to have a quantity field on my product listing archive on single product page. It works fine, but not with product archive listing.
Here are the scenario:
— default Quantity is 1
— I change it to 2
— add this product to cart
— Quantity in the cart is 2
— change that quantity to any i.e: 5
— add same product to cart again
— Quantity in the cart increased by.. 2! not adding 5
(even though [data-quantity] attribute is changed correctly)
— so now Quanity is 4 instead of 7 increased by 5
I tried it on fresh install of wordpress and using twenty sixteen themes and deactivated all plugins. Here are my code that I used, is there any additional filter to do this on product listing archive?
function custom_quantity_field_archive() {
$product = wc_get_product( get_the_ID() );
if ( ! $product->is_sold_individually() && 'variable' != $product->product_type && $product->is_purchasable() ) {
woocommerce_quantity_input( array( 'min_value' => 1, 'max_value' => $product->backorders_allowed() ? '' : $product->get_stock_quantity() ) );
}
}
add_action( 'woocommerce_after_shop_loop_item', 'custom_quantity_field_archive', 31);
/**
* Add requires JavaScript. uzzyraja.com/sourcecodes/
*/
function custom_add_to_cart_quantity_handler() {
wc_enqueue_js( '
jQuery( ".post-type-archive-product" ).on( "change input", ".quantity .qty", function() {
var add_to_cart_button = jQuery( this ).parents( ".product" ).find( ".add_to_cart_button" );
// For AJAX add-to-cart actions
add_to_cart_button.attr( "data-quantity", jQuery( this ).val() );
// For non-AJAX add-to-cart actions
add_to_cart_button.attr( "href", "?add-to-cart=" + add_to_cart_button.attr( "data-product_id" ) + "&quantity=" + jQuery( this ).val() );
});
' );
}
add_action( 'init', 'custom_add_to_cart_quantity_handler' );

Add Woocommerce Default Product Sorting

I need to change the default sorting to another sorting.
I want on my /shop/ page category and tags pages the products to show by default the last modified.When i edit a product and i change something inside the product to move on the first row.
Is there anyone who can help me with this please?
Best Regards
WooCommerce - Change default catalog sort order. Similarly do for shop page, etc by hooks.
/**
* This code should be added to functions.php of your theme
**/
add_filter('woocommerce_default_catalog_orderby', 'custom_default_catalog_orderby');
function custom_default_catalog_orderby() {
return 'post_modified'; // Can also use title and price
}
[or]
add_filter('woocommerce_get_catalog_ordering_args', 'am_woocommerce_catalog_orderby');
function am_woocommerce_catalog_orderby( $args ) {
$args['orderby'] = 'last_modified';
$args['order'] = 'desc';
return $args;
}
Ref: https://gist.github.com/mikejolley/1622323
Or ref : this can do it in admin panel. but need to add the hooks in functions.php as mentioend above . Manageable in woocomerce admin panel.
http://www.remicorson.com/woocommerce-sort-products-from-oldest-to-most-recent/
Try this option it worked for me fine .
This worked for me. Manageable in woocomerce admin panel. http://www.remicorson.com/woocommerce-sort-products-from-oldest-to-most-recent/ . Add the following in your current theme (functions.php) file.
// Filters
add_filter( 'woocommerce_get_catalog_ordering_args', 'custom_woocommerce_get_catalog_ordering_args' );
add_filter( 'woocommerce_default_catalog_orderby_options', 'custom_woocommerce_catalog_orderby' );
add_filter( 'woocommerce_catalog_orderby', 'custom_woocommerce_catalog_orderby' );
// Apply custom args to main query
function custom_woocommerce_get_catalog_ordering_args( $args ) {
$orderby_value = isset( $_GET['orderby'] ) ? woocommerce_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
if ( 'oldest_to_recent' == $orderby_value ) {
$args['orderby'] = 'post_modified';
$args['order'] = 'DESC';
}
return $args;
}
/* Create new sorting method */
function custom_woocommerce_catalog_orderby( $sortby ) {
$sortby['oldest_to_recent'] =
__( 'Based on Last modified to be displayed recent', 'woocommerce' );
return $sortby;
}
Go to your admin panel http://localhost/wpppame/wp-admin/admin.php?page=wc-settings&tab=products&section=display and then you will see the new option added. Select it and click save. Then go to front end of localhost/wpppame/shop, you can see the changes in the page.

Resources