I am trying to AJAXify my Woocommerce cart but I am failing hard and I really can't find any help or documentation (I searched for days). So any help is desperately appreciated.
I tried two approaches:
Custom AJAX Function
When changing the quantity (on the cart page), a AJAX call is fired (-> admin-ajax.php) which triggers a function in my functions.php:
function setQty() {
global $woocommerce;
WC()->cart->set_quantity( $_POST['itemKey'], $_POST['quantity'], true);
echo json_encode(array('totalCount'=>WC()->cart->get_cart_contents_count(), 'total'=>$woocommerce->cart->total)); }
The echoed JSON String contains the correct number of items in cart but the total amount is 0. When I reload the page the altered quantity is not saved.
Same with
WC()->cart->add_to_cart($product_id, $quantity) or adding WC()->cart->calculate_totals()
I tried it this way so i can format the values I need to update my cart how i want.
What am I missing here in order to get the cart update saved?
The woocommerce built-in AJAX update function doesn't trigger, because I have a custom design and I think it needs a specific HTML-structure in order to work properly but i can't find any documentation or examples. Also I need the updated values (total amount, total count etc.) in a custom format. So far it just passes me "updated fragments" as predefined html code.
How do i need to build the HTML code of my cart.php that the ajax update will work? And how do i alter the returning values?
Thank you very much in advance.
I'm not sure what you'd like to update, but I guess you want to update the totals amount of products in the basket.
This example replaces and updates the HTML
Let's say you have a div where your total amount is in:
<div class="cart-totals"><?php echo WC()->cart->get_cart_contents_count(); ?></div>
Add this to your functions.php:
// Mini Cart update with AJAX
add_filter( 'woocommerce_add_to_cart_fragments', 'custom_cart_count_fragments', 10, 1 );
function custom_cart_count_fragments( $fragments ) {
$fragments['div.cart-totals'] = '<div class="cart-totals">' . WC()->cart->get_cart_contents_count() . '</div>';
return $fragments;
}
Note: You are replacing not adding
Is it a mini cart/counter you are trying to create or a full page to review/remove products?
If it is a mini-cart/cart counter you wanted, I've created a repo under https://github.com/samisonline/ajax_cart for you that has the basic functionality baked in. This may not be the exact format you're looking for, but it shows the woocommerce functionality at work, as well as the needed markup for AJAX to work!
Related
I'm figuring out a filter but can't be figured :)
Just want to change PrimaryImageOfPage value with an og:image value in CollectionPage for Taxonomies.
It may be that I have to use woocommerce_structured_data_product to filter here and look for the image $markup['image'] = $image;
I have created some filters, but it isn't woocommerce_structured_data_product I guess.
One of them was like that but it... nah.
add_filter( 'woocommerce_structured_data_product', function( $markup ) {
$markup['image'] = ('rank_math/opengraph/{$network}/image');
return $markup;
});
What am I doing wrong? I have been doing this whole day -_-
If You inspect the code of the class WC_Structured_Data, You would see that woocommerce_structured_data_product filter is executed inside function generate_product_data
WC Complete Source of the class WC_Structured_Data : https://github.com/woocommerce/woocommerce/blob/b88b868ab8919b7c854173098b7d6d4ab227f9ee/includes/class-wc-structured-data.php
$this->set_data( apply_filters( 'woocommerce_structured_data_product', $markup, $product ) );
And generate_product_data function is executed on action woocommerce_single_product_summary
add_action( 'woocommerce_single_product_summary', array( $this, 'generate_product_data' ), 60 );
So, your code would work on product single page only and not archive/list pages, such as the taxonomy page.
The feature you want to achieve is not feasible out of the box in WC, You will need to customize yourself.
Logically, structured data on a single product page is feasible due to the fact there is only one product and product information is available, on the other hand, product list has more than one product (you might need to consider like you want to show details of first product) so it is ambiguous and not feasible out of the box for WC.
I want to add the parent price to all variations using "Create variations from all attributes > go"
- but when I add action it won't even show my debug echo text.
I'm trying to add an action to this hook
do_action( 'product_variation_linked', $variation_id );
Here: public function create_all_product_variations
in this file: class-wc-product-data-store-cpt.php line 1189
Instead of echoing my debug text it just messes up the alert confirmation and doesn't allow the created variations to show using Ajax. They are created though. They display fine on refresh.
Any idea why the hook doesn't operate as one would expect?
I guess it has something do do with Ajax?
I guess plan B is to write a function that updates all variations. Could also generate the variations after import too and bypass the whole product > go GUI?
Thanks
I want to limit the number of items a user can have in cart to a maximum of 1 item (regardless the quantity).
There are several answers about how to achieve this using 'woocommerce_add_to_cart_validation' & 'woocommerce_update_cart_validation' filters (e.g. answer 1, answer 2, answer 3, ...).
It's also possible to use existing plugins like this one but it doesn't support maximum number of items limit.
However, in my case, both filters didn't fire due to the customization to 'Add to cart' logic that is done by the theme I'm using (for business/technical reasons that are irrelevant to discuss here).
That said, I need to achieve the same functionality using a different solution (using another filters, ...).
To achieve the required functionality, this can be done by using 'woocommerce_add_cart_item' filter as follows:
add_filter( 'woocommerce_add_cart_item' , 'validate_cart_max_items');
function validate_cart_max_items( $item_data ) {
// Check total cart quantity
$cart_contents_count = WC()->cart->get_cart_contents_count();
// If quantity > 0, cancel current item addition to cart & display an error message
if($cart_contents_count > 0) {
$item_data = NULL;
wc_add_notice( "A maximum of 1 item can be added to your cart", "error" );
}
return $item_data;
}
The above code snippet should be added to functions.php file under your active theme folder.
This code snippet has been tested using WordPress v5.3.1 and WooCommerce v3.8.1
i have tried many way but can not figure out. I want to hide basic price (top price) of product details page and want to replace with bottom price (total price). Something like THIS. Could anyone tell me how i do that? is there any hook in woocommerce for do this?
I have tried with this hook:
remove_action('woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_price',10);
But it does't work. Thanks me advance.
Two big points here.
Your code is referencing the shop loop, while your screen shot is the single product page. Since your code is targeting the wrong page, you aren't likely to see any change.
remove_action() always needs to be called from inside a function and not directly from your theme's functions.php. See the codex.
So, taking those points into consideration, something like the following ought to remove the price from the single product page.
function so_46304892_remove_price() {
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
}
add_action( 'woocommerce_before_single_product', 'so_46304892_remove_price' );
You can use this hook woocommerce_get_price_html and check whether it is a single product page or not
For eg.
add_filter('woocommerce_get_price_html','your_func_name',10,2);
function your_func_name($price, $product_data) {
if(is_product()) {
$price = '';
}
return $price;
}
I'm looking to reorder the product table on the Cart page in WooCommerce on WordPress. Currently the products listed go from oldest - newest (from order of adding to cart) and want to have the opposite, looking to have most recent added on top and oldest on bottom.
do_action( 'woocommerce_before_cart' ); ?>
<div class="cart_container">
<form class="cart-form" action="<?php echo esc_url( WC()->cart->get_cart_url() ); ?>" method="post">
<?php do_action( 'woocommerce_before_cart_table' ); ?>
Would it be possible to add orderby when calling the cart_url?
To do any kind of cart ordering you have to use
woocommerce_cart_loaded_from_session hook; and to reverse the
order simply use PHP array_reverse function.
Here is the code:
add_action('woocommerce_cart_loaded_from_session', 'wh_cartOrderItemsbyNewest');
function wh_cartOrderItemsbyNewest() {
//if the cart is empty do nothing
if (WC()->cart->get_cart_contents_count() == 0) {
return;
}
//array to collect cart items
$cart_sort = [];
//add cart item inside the array
foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {
$cart_sort[$cart_item_key] = WC()->cart->cart_contents[$cart_item_key];
}
//replace the cart contents with in the reverse order
WC()->cart->cart_contents = array_reverse($cart_sort);
}
Code goes in function.php file of your active child theme (or theme). Or also in any plugin php files.
Code is tested and works.
Hope this helps!
The accepted answer has one major flaw: it creates a race condition and an infinite AJAX refresh loop with multiple tabs open (see here).
The way I was able to get around this is using action hooks:
Before the cart contents are looped through, we reverse the contents and save the new, reversed order
After the cart contents are looped through, we repeat step 1 to restore the original order
There are three areas (by default) where the cart items are looped on the frontend, so the action hooks I use cover each of those areas.
Here's the tested code:
function reverse_cart_contents() {
$cart_contents = WC()->cart->get_cart_contents();
if($cart_contents) {
$reversed_contents = array_reverse($cart_contents);
WC()->cart->set_cart_contents($reversed_contents);
}
}
add_action('woocommerce_before_mini_cart', 'reverse_cart_contents');
add_action('woocommerce_after_mini_cart', 'reverse_cart_contents');
add_action('woocommerce_before_cart', 'reverse_cart_contents');
add_action('woocommerce_after_cart', 'reverse_cart_contents');
add_action('woocommerce_review_order_before_cart_contents', 'reverse_cart_contents');
add_action('woocommerce_review_order_after_cart_contents', 'reverse_cart_contents');
You can modify woocommerce plugin's cart/cart.php template file. When loop starts with "WC()->cart->get_cart()" on cart page, you can first take this array into a separate one, reverse and then use this reversed array for showing cart products in reverse order.
This option is suggested because you don't actually interact with woocommerce object and hence it involves lesser processing. You're just showing them upside down.