Refresh a custom component on cart events in Woocommerce - php

I have a component called cart checkout that is displayed on a the woocommerce archive-product.php page. When someone clicks add to card on one of the products on this page I want this component to update to show the amount of items, the name and the price. I am currently using the following code to display this information, but you have to refresh the page to see it updated after hitting add to cart.
<div class="cart-wrap">
<p class="cart-title">Currently in Cart</p>
<?php
global $woocommerce;
$items = $woocommerce->cart->get_cart();
foreach($items as $item => $values) {
$_product = wc_get_product( $values['data']->get_id());
echo "<p>" . $_product->get_title().'<span class="amount"> x '.$values['quantity'];
$price = get_post_meta($values['product_id'] , '_price', true);
echo " $".$price."</span></p>";
}
?>
<a class="cart-checkout" href="<?php echo wc_get_cart_url(); ?>" >Checkout</a>
</div>
I want to use ajax I would assume but don't even know where to start to figure out how to get it to work.
Ok thanks ahead of time.

To ajaxify cart components (or called in Woocommerce fragments), you will use the following:
1) your revisited code component:
<div class="cart-wrap">
<p class="cart-title"><?php _e("Currently in Cart", "woocommerce"); ?></p>
<div id="cart-items-wrap">
<?php
foreach( WC()->cart->get_cart() as $cart_item ) {
printf( '<p>%s<span class="amount"> x %s %s</span></p>',
$cart_item['data']->get_title(),
$cart_item['quantity'],
wc_price( wc_get_price_to_display( $cart_item['data'] ) )
);
}
?>
</div>
<a class="cart-checkout" href="<?php echo wc_get_cart_url(); ?>"><?php _e("Checkout", "woocommerce"); ?></a>
</div>
2) The hooked function that will ajax refresh your component:
add_filter( 'woocommerce_add_to_cart_fragments', 'ajaxify_components', 10, 1 );
function ajaxify_components( $fragments ) {
ob_start();
?>
<div id="cart-items-wrap">
<?php
foreach( WC()->cart->get_cart() as $cart_item ) {
printf( '<p>%s<span class="amount"> x %s %s</span></p>',
$cart_item['data']->get_title(),
$cart_item['quantity'],
wc_price( wc_get_price_to_display( $cart_item['data'] ) )
);
}
?>
</div>
<?php
$fragments['#cart-items-wrap'] = ob_get_clean();
return $fragments;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

Related

How to Get Value from input fields in cart page to admin order details page?

In the cart page, I already created two text fields, but I'm unable to get the value that user input in that fields to admin order details page.
How can I get the values in order details page and I also want to save that details in the database.
Below is the code of my cart page
<?php
do_action( 'woocommerce_before_cart' ); ?>
<section class="checkout_display">
<div class="container">
<div class="row">
<form action="<?php echo esc_url( wc_get_checkout_url() );?>" method="post">
<?php do_action( 'woocommerce_before_cart_table' ); ?>
<div class="col-lg-6 col-md-8 col-sm-12 inset">
<div class="checkout_title">get started</div>
<div class="first_form">
<!--Code which display text field one -->
<div class="form-group" >
<label>Instagram username</label>
<input type="text" name="igusername" required>
</div>
<!--Code which display text field second -->
<div class="form-group">
<label>Email</label>
<input type="email" name="useremail" required>
</div>
<?php do_action( 'woocommerce_before_cart_contents' ); ?>
<?php
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
$product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key );
if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
$product_permalink = apply_filters( 'woocommerce_cart_item_permalink', $_product->is_visible() ? $_product->get_permalink( $cart_item ) : '', $cart_item, $cart_item_key );
?>
<div class="form-group">
<label>Your package</label>
<select disabled>
<option> <?php echo wp_kses_post( apply_filters( 'woocommerce_cart_item_name', sprintf( '%s', esc_url( $product_permalink ), $_product->get_name() ), $cart_item, $cart_item_key ) );?> For
<span><?php echo apply_filters( 'woocommerce_cart_item_price', WC()->cart->get_product_price( $_product ), $cart_item, $cart_item_key ); // PHPCS: XSS ok.
?>
</span>
</option>
</select>
</div>
<div class="checkbox"><input type="checkbox" /> Yes! send me special promotion and discounts</div>
<div class="btn">
<input type="submit" value="next">
</a>
</div>
<?php
}
}
?>
<?php do_action( 'woocommerce_cart_contents' ); ?>
<?php do_action( 'woocommerce_after_cart_contents' ); ?>
</div>
</div>
<?php do_action( 'woocommerce_after_cart_table' ); ?>
</form>
</div>
</div>
</section>
<?php do_action( 'woocommerce_after_cart' ); ?>
Code which display text field one and second are the text box from where i want to get value which user input and want to display and store them in admin order details page after completion of payment
Try the following that will display your posted fields values to Woocommerce session. When order will be placed, it will saved that custom session data as custom order meta data and display it in admin orders:
// Save the posted data to Woocommerce session
add_filter( 'init', 'set_instagram_posted_data_to_wc_sessions', 10, 3 );
function set_instagram_posted_data_to_wc_sessions() {
if ( ( is_cart() || is_checkout() ) && isset($_POST['igusername']) && isset($_POST['useremail']) ) {
// Enable Woocommerce sessions (if not done yet)
if ( isset(WC()->session) && ! WC()->session->has_session() ) {
WC()->session->set_customer_session_cookie( true );
}
$session_data = []; // initializing
if( isset($_POST['igusername']) && ! empty($_POST['igusername']) ) {
// Add the dropdown value as custom cart item data
$session_data['ig_username'] = sanitize_text_field($_POST['igusername']);
}
if( isset($_POST['useremail']) && ! empty($_POST['useremail']) ) {
// Add the dropdown value as custom cart item data
$session_data['ig_useremail'] = sanitize_email($_POST['useremail']);
}
// Set the data to custom wc_sessions
if( sizeof($session_data) > 0 ) {
WC()->session->set('ig_data', $session_data);
}
}
}
// Save the session data as custom order meta data (post meta data)
add_action( 'woocommerce_checkout_create_order', 'action_checkout_create_order_callback', 10, 2 );
function action_checkout_create_order_callback( $order, $data ) {
if( $session_data = WC()->session->get('ig_data') ) {
$order->update_meta_data( '_ig_username', wc_clean($session_data['ig_username']) );
$order->update_meta_data( '_ig_useremail', wc_clean($session_data['ig_useremail']) );
// remove the data from Woocommerce session
WC()->session->__unset('ig_data'):
}
}
// Display custom data in Admin orders, below the billing address
add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_after_admin_order_billing_address', 10, 1 );
function display_after_admin_order_billing_address( $order ){
$ig_username = $order->get_meta('_ig_username');
$ig_useremail = $order->get_meta('_ig_useremail');
if( ! empty($ig_username) || ! empty($ig_useremail) ) :
echo '<div class="instagram-userdata">
<h3>'.__('Instagram user data').'</h3>
<table cellpadding="0" cellspacing="0" border="0" style="margin-top:6px;">
<tr><th align="left">'.__('Username').': </th><td> ' . $ig_username . '</td></tr>
<tr><th align="left">'.__('Email').': </th><td> ' . $ig_useremail . '</td></tr>
</table>
</div>';
endif;
}
Code goes in function.php file of your active child theme (or active theme). It should works now.
If it doesn't work with sessions you can use the following that will add the post data to hidden fields in checkout page and will post that data again when order is submitted… Everything else is the same as above…
So you can try alternatvelly:
// Display the posted data values in checkout hidden fields
add_filter( 'woocommerce_after_checkout_billing_form', 'set_instagram_posted_data_in_hidden_field', 10, 3 );
function set_instagram_posted_data_in_hidden_field() {
if ( isset($_REQUEST['igusername'])|| isset($_REQUEST['useremail']) ) {
// Display hidden fields with the Instagram posted values
?><input type="hidden" name="ig_username" value="<?php echo $_REQUEST['igusername']; ?>">
<input type="hidden" name="ig_useremail" value="<?php echo $_REQUEST['useremail']; ?>"><?php
}
}
// Save checkout hidden fields values as custom order meta data (post meta data)
add_action( 'woocommerce_checkout_create_order', 'action_checkout_create_order_callback', 10, 2 );
function action_checkout_create_order_callback( $order, $data ) {
if ( isset($_POST['ig_username']) {
$order->update_meta_data( '_ig_username', sanitize_text_field($_POST['ig_username']) );
}
if ( isset($_POST['ig_useremail']) {
$order->update_meta_data( '_ig_useremail', sanitize_email($session_data['ig_useremail']) );
}
}
// Display custom data in Admin orders, below the billing address
add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_after_admin_order_billing_address', 10, 1 );
function display_after_admin_order_billing_address( $order ){
$ig_username = $order->get_meta('_ig_username');
$ig_useremail = $order->get_meta('_ig_useremail');
if( ! empty($ig_username) || ! empty($ig_useremail) ) :
echo '<div class="instagram-userdata">
<h3>'.__('Instagram user data').'</h3>
<table cellpadding="0" cellspacing="0" border="0" style="margin-top:6px;">
<tr><th align="left">'.__('Username').': </th><td> ' . $ig_username . '</td></tr>
<tr><th align="left">'.__('Email').': </th><td> ' . $ig_useremail . '</td></tr>
</table>
</div>';
endif;
}
Code goes in function.php file of your active child theme (or active theme). It should works now.
In Order pages in backend, you will get something like:
To retrieve the data from $order the WC_Order Object (or $order_id the Order Id) use:
$order = wc_get_order( $order_id ); // (optionally if required) with the Order ID
$ig_username = $order->get_meta('_ig_username');
$ig_useremail = $order->get_meta('_ig_useremail');
You can use order meta to save anything to a particular order.
add_action('woocommerce_checkout_create_order',
'before_checkout_create_order', 20, 2);
function before_checkout_create_order( $order, $data )
{
$order->update_meta_data( '_custom_text1', 'value' );
$order->update_meta_data( '_custom_tex2', 'value' );
}
Add your text box values to the value section of the meta key and they will store in the DB when the order is saved.
They will appear at the bottom of the order screen in admin section

Empty Cart button in Mini Cart. woocommerce

Is it possible to add an empty cart button inside a mini cart? I managed to do that on a cart page but having issue with a mini cart.
add_action( 'woocommerce_widget_shopping_cart_buttons', 'add_clear_cart_button', 20 );
function add_clear_cart_button() {
echo "<a class='button' href='?empty-cart=true'>" . __( 'Empty Cart', 'woocommerce' ) . "</a>";
}
Am I using a wrong action?
add below function in function.php for empty cart button
<?php
// check for empty-cart get param to clear the cart
add_action( 'init', 'woocommerce_clear_cart_url' );
function woocommerce_clear_cart_url() {
global $woocommerce;
if ( isset( $_GET['empty-cart'] ) ) {
$woocommerce->cart->empty_cart();
}
}
add_action( 'woocommerce_widget_shopping_cart_buttons', 'add_clear_cart_button', 10, 2 );
function add_clear_cart_button() {
?>
<a class="button" href="<?php echo $woocommerce->cart->get_cart_url(); ?>?empty-cart"><?php _e( 'Empty Cart', 'woocommerce' ); ?></a>
<?php
}
?>

Wordpress - using Ajax on Woocommerce add to cart button shortcodes

I have a pretty strange problem with a custom build I am doing in Wordpress. I am using hooks to overwrite a starter theme's 'add-to-cart' button on a custom page showing products. The weird thing is that when I loop through the add-to-cart button to add quantity options on my products, the original Ajax function disappears. I then implemented another function to add it back in (and cause my custom 'view cart' button's items-in-cart number to update) but although it works in the cart, it doesn't seem to be working for my custom shop page.
I am using this snippet in my header to handle the cart contents:
<?php if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
$count = WC()->cart->cart_contents_count;
?><a class="cart-contents" href="<?php echo WC()->cart->get_cart_url(); ?>" title="<?php _e( 'View your shopping cart' ); ?>"><?php
if ( $count > 0 ) {
?>
<span class="cart-contents-count"><?php echo esc_html( $count ); ?></span>
<?php
}
?></a>
And here are my two functions in my child-theme functions.php:
/**
* Ensure cart contents update when products are added to the cart via AJAX
*/
function my_header_add_to_cart_fragment( $fragments ) {
ob_start();
$count = WC()->cart->cart_contents_count;
?><a class="cart-contents" href="<?php echo WC()->cart->get_cart_url(); ?>" title="<?php _e( 'View your shopping cart' ); ?>"><?php
if ( $count > 0 ) {
?>
<span class="cart-contents-count"><?php echo esc_html( $count ); ?></span>
<?php
}
?></a><?php
$fragments['a.cart-contents'] = ob_get_clean();
return $fragments;
}
add_filter( 'woocommerce_add_to_cart_fragments', 'my_header_add_to_cart_fragment' );
/**
* Add quantity to products in Products Page
*/
add_filter( 'woocommerce_loop_add_to_cart_link', 'quantity_inputs_for_woocommerce_loop_add_to_cart_link', 10, 2 );
function quantity_inputs_for_woocommerce_loop_add_to_cart_link( $html, $product ) {
if ( $product && $product->is_type( 'simple' ) && $product->is_purchasable() && $product->is_in_stock() && ! $product->is_sold_individually() ) {
$html = '<form action="' . esc_url( $product->add_to_cart_url() ) . '" class="cart" method="post" enctype="multipart/form-data">';
$html .= woocommerce_quantity_input( array(), $product, false );
$html .= '<button type="submit" class="button alt">' . esc_html( $product->add_to_cart_text() ) . '</button>';
$html .= '</form>';
}
return $html;
}
I think that my second function adding a new add-to-cart button is overwriting the initial Ajax functionality, but everything I try to do to add this functionality back in is not working. I'm not the best at JS/jQuery so it's probably that I'm not implementing my code properly.
Any help with this would be much appreciated.
Need to add another classes to the button i.e add_to_cart_button & ajax_add_to_cart.
Hope this will do for you.

Woocommerce - Display product excerpt in Orders page

I need to show the product's excerpt in the Orders page. I spent several hours trying to find a solution but nothing.
I already show the image & the title of the product (Thanks to #helgatheviking & this thread) , but I can't get the excerpt to show. This is my code:
<div id="order-column" class="my_account_orders">
<div class="wrap">
<?php
foreach ( $customer_orders as $customer_order ) {
$order = wc_get_order( );
$order->populate( $customer_order );
foreach( $order->get_items() as $item_id => $item ) {
$product = apply_filters( 'woocommerce_order_item_product', $order->get_product_from_item( $item ), $item );
$product->get_image();
$product->get_title();
}
$item_count = $order->get_item_count();
?>
<div class="orders-wrap">
<div class="preview">
<div class="image">
<div class="image-wrap"><?php echo $product->get_image(); ?></div>
</div>
<div class="bottom">
<div class="details">
<h3 class="name"><a title="View Order" href="<?php echo $order->get_view_order_url(); ?>"><?php echo $product->get_title(); ?></a></h3>
<h4 class="subtitle"><?php the_excerpt(); ?></h4>
</div>
</div>
The excerpt should appear in subtitle.
I have checked and tried the suggestions in these threads:
Woocommerce - description in products page
Adding a product description to the woocommerce cart page
This should do it. the_excerpt can only be used in combination with the_post() as it depends on the global $post object. But this pretty much reassembles what happens inside it.
<h4 class="subtitle"><?php echo apply_filters( 'the_excerpt', $product->post->post_excerpt ); ?></h4>
A bit late but always use this here:
get_the_excerpt( $product->get_id() );
The other solution from Johan Palmfjord will work but WooCommerce says that you never should access the product data directly.

how to direct woocommerce cart content to shop page?

Hi im using this code from woocommerce to insert a cart content on my site. Does somebody know how i can modify this code so if it shows 0 on the cart it will direct me to the shop page instead of the cart page?
<?php global $woocommerce; ?>
<a class="cart-contents" href="<?php echo $woocommerce->cart->get_cart_url(); ?>" title="<?php _e('View your shopping cart', 'woothemes'); ?>"><?php echo sprintf(_n('%d item', '%d items', $woocommerce->cart->cart_contents_count, 'woothemes'), $woocommerce->cart->cart_contents_count);?> - <?php echo $woocommerce->cart->get_cart_total(); ?></a>
// Ensure cart contents update when products are added to the cart via AJAX (place the following in functions.php)
add_filter('add_to_cart_fragments', 'woocommerce_header_add_to_cart_fragment');
function woocommerce_header_add_to_cart_fragment( $fragments ) {
global $woocommerce;
ob_start();
?>
<a class="cart-contents" href="<?php echo $woocommerce->cart->get_cart_url(); ?>" title="<?php _e('View your shopping cart', 'woothemes'); ?>"><?php echo sprintf(_n('%d item', '%d items', $woocommerce->cart->cart_contents_count, 'woothemes'), $woocommerce->cart->cart_contents_count);?> - <?php echo $woocommerce->cart->get_cart_total(); ?></a>
<?php
$fragments['a.cart-contents'] = ob_get_clean();
return $fragments;
}
If you want to redirect to shop when cart is empty, you can use action hook 'template_redirect' as follows :
add_action( 'template_redirect', 'my_template_redirect' );
function my_template_redirect()
{
if ( is_page( wc_get_page_id( 'cart' ) ) && sizeof( WC()->cart->get_cart() ) == 0 )
{
wp_redirect( get_permalink( wc_get_page_id( 'shop' ) ) );
exit;
}
}
If you are using some other page to show cart content, then you have to modify first condition of if statement, to check if the page is the one that shows cart content.

Categories