I need a quantity selection block in the add to cart loop on the product list page in woocommerce. Woocommerce codex has a page which allows me to do it by basically putting this block of code instead of the existing one:
<form action="<?php echo esc_url( $product->add_to_cart_url() ); ?>" class="cart" method="post" enctype='multipart/form-data'>
<?php woocommerce_quantity_input(); ?>
<button type="submit" class="button alt"><?php echo $label; ?></button>
</form>
However, that form doesn't add to my current AJAX setup and other nice tricks that come with my original add to cart button.
This is the original code of the add to cart button, which works like i want it, except for missing the quantity input:
<?php
/**
* Loop Add to Cart
*
* #author WooThemes
* #package WooCommerce/Templates
* #version 2.1.0
*/
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
global $product, $jckqv;
$jckqv->displayBtn($product->id);
echo '<div class="product-buttons">';
echo apply_filters( 'woocommerce_loop_add_to_cart_link',
sprintf( '%s',
esc_url( $product->add_to_cart_url() ),
esc_attr( $product->id ),
esc_attr( $product->get_sku() ),
$product->is_purchasable() ? 'add_to_cart_button' : '',
esc_attr( $product->product_type ),
esc_html( $product->add_to_cart_text() )
),
$product );
echo do_shortcode('[yith_compare_button]');
echo do_shortcode('[yith_wcwl_add_to_wishlist]');
echo '</div>';
I need to somehow put the woocommerce_quantity_input in this code, to retain the current functionality, but to add the quantity input. I tried to do it in many various ways, but unfortunately my PHP skills lack.
Please help.
Thank you
For anybody who might still need to use this
<?php woocommerce_quantity_input(); ?>
You need to echo it. As easy as that
Related
I have 2 product attributes on my products: color and size. They are rendered in that order. I need to switch them, so that size always comes first.
The WooCommerce file single-product/add-to-cart/variable.php seems responsible for the output, but I am not skilled enough to suggest a change to this code, that would make it order by attribute_id, attribute_name, or reverse default order. Right now they seem to order by a taxonomy term or slug rather than actual attribute data, changing ID or name of attributes in the woocommerce_attribute_taxonomies table does not help.
Please help me crack this.
I have searched for this without luck, the answer might be hidden among the many questions about attribute term order which is NOT what I am asking here.
EDIT: I have thousands of products, so manual per-product reordering won't work.
$attribute_keys = array_keys( $attributes );
do_action( 'woocommerce_before_add_to_cart_form' ); ?>
<form class="variations_form cart" action="<?php echo esc_url( apply_filters( 'woocommerce_add_to_cart_form_action', $product->get_permalink() ) ); ?>" method="post" enctype='multipart/form-data' data-product_id="<?php echo absint( $product->get_id() ); ?>" data-product_variations="<?php echo htmlspecialchars( wp_json_encode( $available_variations ) ); // WPCS: XSS ok. ?>">
<?php do_action( 'woocommerce_before_variations_form' ); ?>
<?php if ( empty( $available_variations ) && false !== $available_variations ) : ?>
<p class="stock out-of-stock"><?php esc_html_e( 'This product is currently out of stock and unavailable.', 'woocommerce' ); ?></p>
<?php else : ?>
<table class="variations" cellspacing="0">
<tbody>
<?php foreach ( $attributes as $attribute_name => $options ) : ?>
<tr>
<td class="label"><label for="<?php echo esc_attr( sanitize_title( $attribute_name ) ); ?>"><?php echo wc_attribute_label( $attribute_name ); // WPCS: XSS ok. ?></label></td>
<td class="value">
<?php
wc_dropdown_variation_attribute_options( array(
'options' => $options,
'attribute' => $attribute_name,
'product' => $product,
) );
echo end( $attribute_keys ) === $attribute_name ? wp_kses_post( apply_filters( 'woocommerce_reset_variations_link', '<a class="reset_variations" href="#">' . esc_html__( 'Clear', 'woocommerce' ) . '</a>' ) ) : '';
?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
Update: (related to your edit)
Is not possible to alter this using code, as it's handle by WC_Product_Variable_Data_Store_CPT Class on read_variation_attributes() method and there is no available hook(s) for that.
Also as that data is cached, a filter hook should not be reasonably welcome..
In general your actual problem doesn't occurs for most people, as they set a sorting from start on each product, when adding attributes to a variable product.
Now you could try to change that, on the database, but it seems not possible as the product attributes sorting is based on the index of a serialized array located in wp_postmeta for a variable product post_id using the meta_key = _product_attributes.
Original answer:
In a Variable product settings, under "Product data" (metabox) > Attributes (tab), you can add product attributes. You can also reorder them simply dragging and drop them on the desired positions.
This will affect the order of the product attributes dropdown, in front end, for a variable product. So you don't need any code for that.
In database, the product attributes sorting is based on the index of an array located in wp_postmeta for a variable product post_id using the meta_key = _product_attributes
In WooCommerce, I am trying to add an extra add to cart button below product summary. I successfully added an extra button following this code which works for single products:
add_action( 'woocommerce_single_product_summary', 'custom_button_after_product_summary', 30 );
function custom_button_after_product_summary() {
global $product;
echo "<a href='".$product->add_to_cart_url()."'>add to cart</a>";
}
But if the product is a variation it doesn't work.
please suggest as what to do?
I have revisited your code a bit, and added a 2nd hooked function for variable products:
// For Simple products
add_action( 'woocommerce_single_product_summary', 'second_button_after_product_summary', 30 );
function second_button_after_product_summary() {
global $product;
if( ! $product->is_type( 'variable' ) )
echo '<button type="submit" name="add-to-cart" value="'. esc_attr( $product->get_id() ).'" class="single_add_to_cart_button button alt">'. esc_html( $product->single_add_to_cart_text() ).'</button>';
}
// For Variable products
add_action( 'woocommerce_single_variation', 'second_button_single_variation', 30 );
function second_button_single_variation() {
global $product;
echo '<br>
<button type="submit" class="single_add_to_cart_button button alt">'. esc_html( $product->single_add_to_cart_text() ).'</button>';
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
You will get this on variable products:
The answer #LoicTheAztec provided is correct but its missing the action attribute for the button click event. Here's the corrected code with the action attribute.
// For Simple products
add_action( 'woocommerce_single_product_summary', 'second_button_after_product_summary', 30 );
function second_button_after_product_summary() {
global $product;
if( ! $product->is_type( 'variable' ) )
echo '<button type="submit" name="add-to-cart" value="'. esc_attr( $product->get_id() ).'" action="'.esc_url( apply_filters( 'woocommerce_add_to_cart_form_action', $product->get_permalink() ) ).'" class="single_add_to_cart_button button alt">'. esc_html( $product->single_add_to_cart_text() ).'</button>';
}
If you are using external products or variation items add the action attribute appropriately. Please refer "plugins/woocommerce/templates/single-product/add-to-cart"
I am using Wordpress with woocommerce and trying to set up some variable products. But variable products show the "In Stock" messages directly below the input/select field. I want it to be shown below the "Add to cart" button.
I am using a child theme for the files, simple.php, variable.php and variation.php.
Feel free to look at the picture to see what I want to do.
http://art-wood.de/instock-move.png
Currently my variable.php looks like this:
<?php
/**
* Variable product add to cart
*
* This template can be overridden by copying it to yourtheme/woocommerce/single-product/add-to-cart/variable.php.
*
* HOWEVER, on occasion WooCommerce will need to update template files and you (the theme developer).
* will need to copy the new files to your theme to maintain compatibility. We try to do this.
* as little as possible, but it does happen. When this occurs the version of the template file will.
* be bumped and the readme will list any important changes.
*
* #see http://docs.woothemes.com/document/template-structure/
* #author WooThemes
* #package WooCommerce/Templates
* #version 2.5.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
global $product;
$attribute_keys = array_keys( $attributes );
do_action( 'woocommerce_before_add_to_cart_form' ); ?>
<form class="variations_form cart" method="post" enctype='multipart/form-data' data-product_id="<?php echo absint( $product->id ); ?>" data-product_variations="<?php echo htmlspecialchars( json_encode( $available_variations ) ) ?>">
<?php do_action( 'woocommerce_before_variations_form' ); ?>
<?php if ( empty( $available_variations ) && false !== $available_variations ) : ?>
<div class="stock out-of-stock"><?php _e( 'This product is currently out of stock and unavailable.', 'woocommerce' ); ?></div>
<?php else : ?>
<span class="variations" cellspacing="0">
<?php foreach ( $attributes as $attribute_name => $options ) : ?>
<label class="label" for="<?php echo sanitize_title( $attribute_name ); ?>"><?php echo wc_attribute_label( $attribute_name ); ?></label>
<div class="value">
<?php
$selected = isset( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ? wc_clean( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) : $product->get_variation_default_attribute( $attribute_name );
wc_dropdown_variation_attribute_options( array( 'options' => $options, 'attribute' => $attribute_name, 'product' => $product, 'selected' => $selected ) );
echo end( $attribute_keys ) === $attribute_name ? apply_filters( 'woocommerce_reset_variations_link', '<a class="reset_variations" href="#">' . __( 'Clear', 'woocommerce' ) . '</a>' ) : '';
?>
</div>
<?php endforeach;?>
</span>
<?php do_action( 'woocommerce_before_add_to_cart_button' ); ?>
<div class="single_variation_wrap">
/**
* woocommerce_before_single_variation Hook.
*/
do_action( 'woocommerce_before_single_variation' );
/**
* woocommerce_single_variation hook. Used to output the cart button and placeholder for variation data.
* #since 2.4.0
* #hooked woocommerce_single_variation - 10 Empty div for variation data.
* #hooked woocommerce_single_variation_add_to_cart_button - 20 Qty and cart button.
*/
do_action( 'woocommerce_single_variation' );
/**
* woocommerce_after_single_variation Hook.
*/
do_action( 'woocommerce_after_single_variation' );
?>
</div>
<?php do_action( 'woocommerce_after_add_to_cart_button' ); ?>
<?php endif; ?>
<?php do_action( 'woocommerce_after_variations_form' ); ?>
</form>
<?php do_action( 'woocommerce_after_add_to_cart_form' ); ?>
Does somebody know how to move the message down below the Add to cart button? This would be amazing! May its a simple add to the functions.php maybe its a switch in the variable.php... I don't know that. Otherwise I wouldn't ask :)
I found the solution by myself. Maybe its useful for someone so here it is ;)
Simply add this to your functions.php
remove_action( 'woocommerce_single_variation' , 'woocommerce_single_variation', 10);
add_action( 'woocommerce_single_variation', 'woocommerce_single_variation', 20 );
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.
I have a problem to remove the link to the shop.
i dont want a link to the shop when the cart is empty.
Here is the original template file:
<?php
/**
* Empty cart page
*
* #author WooThemes
* #package WooCommerce/Templates
* #version 2.0.0
*/
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
?>
<p><?php _e( 'Your cart is currently empty.', 'woocommerce' ) ?></p>
<?php do_action('woocommerce_cart_is_empty'); ?>
<p><a class="button" href="<?php echo get_permalink(woocommerce_get_page_id('shop')); ?>"><?php _e( '← Return To Shop', 'woocommerce' ) ?></a></p>
So i have tryed this in function.php whit out any luck:
remove_action('woocommerce','woocommerce_cart_is_empty');
The answer by Howlin is correct, but you shouldn't edit the file in the woocommerce plugin folder. You should copy the specific template file from woocommerce to your own theme directory and edit that file. Removing the link in the copied file will create the same effect as your desired filter.
Removing
<p class="return-to-shop"><a class="button wc-backward" href="<?php echo apply_filters( 'woocommerce_return_to_shop_redirect', get_permalink( wc_get_page_id( 'shop' ) ) ); ?>"><?php _e( 'Return To Shop', 'woocommerce' ) ?></a></p>
from the cart-page.php page, should do it.