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

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.

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

How can I use WordPress ajax to set a cookie and redirect before a page loads

I’m working on a WordPress site requirement to redirect a user when they’re in a certain country to their country specific homepage.
(I’ve had to do this via WP Ajax because full page caching prevents it working directly on live hosting environment - I was previously doing it quite simply in functions.php hooked into 'init').
This works when I call it at the start of the header template, but only after the current page content is shown. It would be great if I could hook it in to happen before the page is displayed e.g. like using hooks such as: 'wp_loaded', ‘template_redirect’ but jQuery needs to be available...
Here is my code. It needs tidying some more but appreciate any suggestions as how to make a redirect happen before page contents displayed?
function invoke_county_redirection() {
ob_start();
?>
<script type="text/javascript">
var ajax_url = "<?= admin_url( 'admin-ajax.php' ); ?>";
jQuery.post(ajax_url, {
'action': 'country_redirection',
}, function (response) {
// Set the cookie to say we're performing the redirect - this will flag it not to happen again
createCookie('redirected', 'true');
if (response != '') {
window.location.replace(response);
}
function createCookie(name, value, days) {
var expires = "";
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + value + expires + "; path=/";
}
</script>
<?php
echo ob_get_clean();
return;
}
function country_redirection() {
$redirect_url = '';
if ( $_COOKIE['redirected'] !== 'true' ) {
/* declare empty result url */
$result['url'] = '';
/* Call on geoip plugin to get the country from their IP address */
$userInfo = geoip_detect2_get_info_from_current_ip();
$country_code = $userInfo->country->isoCode;
/* if we've retreived the country code for the current user */
if ( $country_code ) {
/* GET THE CORRECT REDIRECT URL IF APPLICABLE TO THE USER COUNTRY */
$redirect_url = get_country_url($country_code);
}
}
echo $redirect_url;
wp_die();
}
add_action( 'wp_ajax_nopriv_country_redirection', 'country_redirection' );
add_action( 'wp_ajax_country_redirection', 'country_redirection' );
Quick update in case anyone else can be helped by this.
I hooked the hooked the function invoke_county_redirection() into the wp_head hook as follows...
add_action('wp_head', "invoke_county_redirection");
This means that jQuery would be loaded and the country detect/redirect process runs.
However, it doesn't make the request syncronous and in this particular scenario with wanting to redirect before the page loads, I have given up on this. There is a minefield of issues trying to get around full page caching trying to store a cookie and do a redirect before the page loads. I should have just insisted that caching remained off where this needs to run, so this is our conclusion. We are instead optimsing the site as best we can with GTMetrix and loader.io and we will cross the bridge of scalability as and when we need to.

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