The Woocommerce template add-to-cart.php contains this code:
echo apply_filters( 'woocommerce_loop_add_to_cart_link', // WPCS: XSS ok.
sprintf( '<a href="%s" data-quantity="%s" class="%s" %s>%s</a>',
esc_url( $product->add_to_cart_url() ),
esc_attr( isset( $args['quantity'] ) ? $args['quantity'] : 1 ),
esc_attr( isset( $args['class'] ) ? $args['class'] : 'button' ),
isset( $args['attributes'] ) ? wc_implode_html_attributes( $args['attributes'] ) : '',
esc_html( $product->add_to_cart_text() )
),
$product, $args );
I need to add this markup to the tag
<div class="icw"><i class="a3"></i></div>
I tried adding it directly but the new element was added after the actual link.
This is what I tried;
sprintf( '<i class="a3"></i></div>%s',
Can anyone explain to me how I go about adding this element?
Many thanks.
Read this before you continue
Is putting a div inside an anchor ever correct?
https://github.com/woocommerce/woocommerce/blob/3.8.0/templates/loop/add-to-cart.php
This template can be overridden by copying it to
yourtheme/woocommerce/loop/add-to-cart.php.
This seems to work without problems
echo apply_filters(
'woocommerce_loop_add_to_cart_link', // WPCS: XSS ok.
sprintf(
'</i>%s',
esc_url( $product->add_to_cart_url() ),
esc_attr( isset( $args['quantity'] ) ? $args['quantity'] : 1 ),
esc_attr( isset( $args['class'] ) ? $args['class'] : 'button' ),
isset( $args['attributes'] ) ? wc_implode_html_attributes( $args['attributes'] ) : '',
esc_html( $product->add_to_cart_text() )
),
$product,
$args
);
Related
Hi Everyone.
So i have found this code shown below: (credit to https://www.tychesoftwares.com/how-to-link-external-products-on-the-shop-page-to-the-product-page-in-woocommerce/)
The quesion i need help with is how to modify this code so it only works on certain product categories, at the moment the code is applied to all products sitewide.
add_filter( 'woocommerce_loop_add_to_cart_link', 'ts_link_external_product_page', 16, 3 );
function ts_link_external_product_page( $button, $product, $args ) {
$url = $product->add_to_cart_url();
$button_text = $product->add_to_cart_text();
if ( 'external' === $product->get_type() ) {
$url = $product->get_permalink();
$button_text = "View Details";
}
return sprintf( '<a href="%s" data-quantity="%s" class="%s" %s>%s</a>',
esc_url($url),
esc_attr( isset( $args['quantity'] ) ? $args['quantity'] : 1 ),
esc_attr( isset( $args['class'] ) ? $args['class'] : 'button' ),
isset( $args['attributes'] ) ? wc_implode_html_attributes( $args['attributes'] ) : '',
esc_html( $button_text)
);
}
I feel like i need to add a line like "if(is_product_category( array( 'catslugurl', 'anothercatslugurl' ) )){" but can not seem to be able to get it to work.
Any help with this would be great. Thank you so much :)
I feel like i need to add a line like "if(is_product_category( array( 'catslugurl', 'anothercatslugurl' ) )){" but can not seem to be able to get it to work.
Try this:
add_filter( 'woocommerce_loop_add_to_cart_link', 'ts_link_external_product_page', 16, 3 );
function ts_link_external_product_page( $button, $product, $args ) {
$url = $product->add_to_cart_url();
$button_text = $product->add_to_cart_text();
$categories = array( 'music', 'clothes' ); //Your specific categories
$product_id = method_exists( $product, 'get_id' ) ? $product->get_id() : $product->id;
if ( has_term( $categories, 'product_cat', $product_id ) && 'external' === $product->get_type() ) {
$url = $product->get_permalink();
$button_text = 'View Details';
}
return sprintf(
'<a href="%s" data-quantity="%s" class="%s" %s>%s</a>',
esc_url( $url ),
esc_attr( isset( $args['quantity'] ) ? $args['quantity'] : 1 ),
esc_attr( isset( $args['class'] ) ? $args['class'] : 'button' ),
isset( $args['attributes'] ) ? wc_implode_html_attributes( $args['attributes'] ) : '',
esc_html( $button_text )
);
}
I have some basic Woocommerce questions and cannot find anywhere online.
from the code below, where are $args come from?
how $product and $args assign to %s ?
thanks!
global $product;
echo apply_filters( 'woocommerce_loop_add_to_cart_link', // WPCS: XSS ok.
sprintf( '<a href="%s" data-quantity="%s" class="%s" %s>%s</a>',
esc_url( $product->add_to_cart_url() ),
esc_attr( isset( $args['quantity'] ) ? $args['quantity'] : 1 ),
esc_attr( isset( $args['class'] ) ? $args['class'] : 'button' ),
isset( $args['attributes'] ) ? wc_implode_html_attributes( $args['attributes'] ) : '',
esc_html( $product->add_to_cart_text() )
),
$product, $args );
1) Explanations for $args variable in template file loop/add_to_cart.php:
The code in your question come from the template file loop/add_to_cart.php.
It is called by content-product.php template file on woocommerce_after_shop_loop_item hook:
/**
* Hook: woocommerce_after_shop_loop_item.
*
* #hooked woocommerce_template_loop_product_link_close - 5
* #hooked woocommerce_template_loop_add_to_cart - 10
*/
do_action( 'woocommerce_after_shop_loop_item' );
As you can see the template function woocommerce_template_loop_add_to_cart() does this job and it is located in WooCommerce plugin under includes/wc-template-functions.php.
So the default arguments are:
$defaults = array(
'quantity' => 1,
'class' => implode(
' ',
array_filter(
array(
'button',
'product_type_' . $product->get_type(),
$product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '',
$product->supports( 'ajax_add_to_cart' ) && $product->is_purchasable() && $product->is_in_stock() ? 'ajax_add_to_cart' : '',
)
)
),
'attributes' => array(
'data-product_id' => $product->get_id(),
'data-product_sku' => $product->get_sku(),
'aria-label' => $product->add_to_cart_description(),
'rel' => 'nofollow',
),
);
They are parsed through the filter hook woocommerce_loop_add_to_cart_args:
$args = apply_filters( 'woocommerce_loop_add_to_cart_args', wp_parse_args( $args, $defaults ), $product );
… allowing to make changes on this arguments.
The $args variable in woocommerce_loop_add_to_cart_link is made of that.
2) How $product and $args are assigned to %s:
This is specific to PHP printf() and sprintf() function where each %s are a placeholder.
In '<a href="%s" data-quantity="%s" class="%s" %s>%s</a>':
the 1st placeholder %s will be replaced by esc_url( $product->add_to_cart_url() )
the 2nd placeholder %s by esc_attr( isset( $args['quantity'] ) ? $args['quantity'] : 1 )
and so on…
Documentation for printf() and sprintf() php functions.
Here is my way of actually changing the $args:
add_filter( 'woocommerce_loop_add_to_cart_args', 'filter_woocommerce_loop_add_to_cart_args', 10, 2 );
function filter_woocommerce_loop_add_to_cart_args( $args, $product ) {
$args['quantity'] = 6;
return $args;
}
In Woocommerce, I Would like co create add to cart link on a simple page of WordPress website (not product page).
So I have tried this code (Where 123 is the product ID):
Buy
I have enabled AJAX add to cart on archives pages Woocommerce option setting.
But It doesn't work and Ajax functionality is not enabled on my custom Add-to-cart link.
How to enable ajax add-to-cart on a custom link (in other pages than woocommerce ones)?
To enable ajax in a custom add to cart button, there is 3 ways at least:
A simple HTML Ajax add to cart link:
<a rel="nofollow" href="/?add-to-cart=37" data-quantity="1" data-product_id="123" data-product_sku="" class="add_to_cart_button ajax_add_to_cart">Add to cart</a>
Using Woocommerce existing [add_to_cart id='123'] shortcode (same usage than above)
The most customizable: A custom shortcode without price included (customizable button text, additional classes, quantity and many others possibilities)
if( ! function_exists('custom_ajax_add_to_cart_button') && class_exists('WooCommerce') ) {
function custom_ajax_add_to_cart_button( $atts ) {
// Shortcode attributes
$atts = shortcode_atts( array(
'id' => '0', // Product ID
'qty' => '1', // Product quantity
'text' => '', // Text of the button
'class' => '', // Additional classes
), $atts, 'ajax_add_to_cart' );
if( esc_attr( $atts['id'] ) == 0 ) return; // Exit when no Product ID
if( get_post_type( esc_attr( $atts['id'] ) ) != 'product' ) return; // Exit if not a Product
$product = wc_get_product( esc_attr( $atts['id'] ) );
if ( ! $product ) return; // Exit when if not a valid Product
$classes = implode( ' ', array_filter( array(
'button',
'product_type_' . $product->get_type(),
$product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '',
$product->supports( 'ajax_add_to_cart' ) ? 'ajax_add_to_cart' : '',
) ) ).' '.$atts['class'];
$add_to_cart_button = sprintf( '<a rel="nofollow" href="%s" %s %s %s class="%s">%s</a>',
esc_url( $product->add_to_cart_url() ),
'data-quantity="' . esc_attr( $atts['qty'] ) .'"',
'data-product_id="' . esc_attr( $atts['id'] ) .'"',
'data-product_sku="' . esc_attr( $product->get_sku() ) .'"',
esc_attr( isset( $classes ) ? $classes : 'button' ),
esc_html( empty( esc_attr( $atts['text'] ) ) ? $product->add_to_cart_text() : esc_attr( $atts['text'] ) )
);
return $add_to_cart_button;
}
add_shortcode('ajax_add_to_cart', 'custom_ajax_add_to_cart_button');
}
This code goes on function.php file of your active child theme (or theme). Tested and works.
USAGE:
In posts and pages text editor:
[ajax_add_to_cart id='123' text='Buy']
In PHP files or templates:
echo do_shortcode( "[ajax_add_to_cart id='123' text='Buy']" );
Inserted in HTML code on a php page:
<?php echo do_shortcode( "[ajax_add_to_cart id='123' text='Buy']" ); ?>
Hide Ajax "view cart"
For custom shortcode, to hide the Ajax "view cart" behavior, you can add in the code, before return $add_to_cart_button; the following:
$style = '<style>a.added_to_cart.wc-forward { display:none !important; }</style>';
$add_to_cart_button = $style . $add_to_cart_button ;
I suggest you to use the [add_to_cart] Shortcode.
Simplest usage with the default parameters:
[add_to_cart id="123" /]
Disables the default style and hides the price:
[add_to_cart id="123" style="" show_price="false" /]
See some sample output
I used this for my plugin and it is working fine:
function wsb_add_to_cart_button( ) {
global $product;
$classes = implode( ' ', array(
'button',
'product_type_' . $product->get_type(),
$product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '',
$product->supports( 'ajax_add_to_cart' ) ? 'ajax_add_to_cart' : '',
) );
return apply_filters( 'woocommerce_loop_add_to_cart_link',
sprintf( '%s',
esc_url( $product->add_to_cart_url() ),
esc_attr( $product->get_id() ),
esc_attr( $product->get_sku() ),
esc_attr( isset( $quantity ) ? $quantity : 1 ),
esc_attr( isset( $classes ) ? $classes : 'button' ),
esc_attr( $product->get_type() ),
esc_html( $product->add_to_cart_text() )
),
$product );
}
for showing button:
<?php echo wsb_add_to_cart_button(); ?>
I'm trying to add the price to the add to cart button in the loop.
[100$ Add to cart] instead of [Add to cart]
add_to_cart.php template:
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() && $product->is_in_stock() ? 'add_to_cart_button' : '',
esc_attr( $product->product_type ),
esc_html( $product->add_to_cart_text() )
),
$product );
price.php template:
<?php if ( $price_html = $product->get_price_html() ) : ?>
<span class="price"><?php echo $price_html; ?></span>
<?php endif; ?>
How do I combine these two? Couldn't find anything on the web.
This should work: modify the add_to_cart.php file to
echo apply_filters( 'woocommerce_loop_add_to_cart_link',
sprintf( '%s %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 ),
$product->get_price_html(),
esc_html( $product->add_to_cart_text() )
),
$product );
and the price will display in front of the "Add to cart" text.
EDIT: You should note that updating the woocommerce plugin will undo that and any other modification you have made to any of the files.
WooCommerce 3.1.0 updated the Functions for Add to Cart Button
apply_filters( 'woocommerce_loop_add_to_cart_link',
sprintf( '<li><a href="%s" rel="nofollow" data-product_id="%s"
data-product_sku="%s" class="btn-filled cart add-to-cart %s
product_type_%s"><i class="fa fa-shopping-cart" ></i></a></li>',
esc_url( $product->add_to_cart_url() ),
esc_attr( isset( $quantity ) ? $quantity : 1 ),
esc_attr( $product->get_id() ),
esc_attr( $product->get_sku() ),
esc_attr( isset( $class ) ? $class : 'button' ),
esc_html( $product->add_to_cart_text() )
),
$product );
If you want to be (somewhat) safe from a future Woocommerce upgrade, follow the official safe way to do it (thank you Felix).
Copy add-to-cart.php into a directory within your theme named /woocommerce keeping the same file structure but removing the /templates/ subdirectory.
Example: To override the admin order notification, copy: wp-content/plugins/woocommerce/templates/emails/admin-new-order.php to wp-content/themes/yourtheme/woocommerce/emails/admin-new-order.php
Here is the file updated for Woocommerce 3.3.0 :
<?php
/**
* Loop Add to Cart
*
* This template can be overridden by copying it to yourtheme/woocommerce/loop/add-to-cart.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 https://docs.woocommerce.com/document/template-structure/
* #author WooThemes
* #package WooCommerce/Templates
* #version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
global $product;
echo apply_filters( 'woocommerce_loop_add_to_cart_link', // WPCS: XSS ok.
sprintf( '%s</span> <span style="color:#999;">|</span> %s',
esc_url( $product->add_to_cart_url() ),
esc_attr( isset( $args['quantity'] ) ? $args['quantity'] : 1 ),
esc_attr( isset( $args['class'] ) ? $args['class'] : 'button' ),
isset( $args['attributes'] ) ? wc_implode_html_attributes( $args['attributes'] ) : '',
$product->get_price_html(),
esc_html( $product->add_to_cart_text() )
),
$product, $args );
?>
Of course, styling the button or modificating its content is entirely up to you and isn't limited to show the product price.
I was having a problem with WooCommerce where the Ajax Add to Cart was only adding 1 despite multiple quantities being selected on Shop Archive Page.
I turned the Ajax off in the settings, and used this solution found on here. I replaced the wp-content/themes/your-theme/templates/loop/add-to-cart.php content with:
<?php
/**
* Custom Loop Add to Cart.
*
* Template with quantity and ajax.
*/
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly.
global $product;
?>
<?php if ( ! $product->is_in_stock() ) : ?>
<?php echo apply_filters( 'out_of_stock_add_to_cart_text', __( 'Read More', 'woocommerce' ) ); ?>
<?php else : ?>
<?php
$link = array(
'url' => '',
'label' => '',
'class' => ''
);
switch ( $product->product_type ) {
case "variable" :
$link['url'] = apply_filters( 'variable_add_to_cart_url', get_permalink( $product->id ) );
$link['label'] = apply_filters( 'variable_add_to_cart_text', __( 'Select options', 'woocommerce' ) );
break;
case "grouped" :
$link['url'] = apply_filters( 'grouped_add_to_cart_url', get_permalink( $product->id ) );
$link['label'] = apply_filters( 'grouped_add_to_cart_text', __( 'View options', 'woocommerce' ) );
break;
case "external" :
$link['url'] = apply_filters( 'external_add_to_cart_url', get_permalink( $product->id ) );
$link['label'] = apply_filters( 'external_add_to_cart_text', __( 'Read More', 'woocommerce' ) );
break;
default :
if ( $product->is_purchasable() ) {
$link['url'] = apply_filters( 'add_to_cart_url', esc_url( $product->add_to_cart_url() ) );
$link['label'] = apply_filters( 'add_to_cart_text', __( 'Add to cart', 'woocommerce' ) );
$link['class'] = apply_filters( 'add_to_cart_class', 'add_to_cart_button' );
} else {
$link['url'] = apply_filters( 'not_purchasable_url', get_permalink( $product->id ) );
$link['label'] = apply_filters( 'not_purchasable_text', __( 'Read More', 'woocommerce' ) );
}
break;
}
// If there is a simple product.
if ( $product->product_type == 'simple' ) {
?>
<form action="<?php echo esc_url( $product->add_to_cart_url() ); ?>" class="cart" method="post" enctype="multipart/form-data">
<?php
// Displays the quantity box.
woocommerce_quantity_input();
// Display the submit button.
echo sprintf( '<button type="submit" data-product_id="%s" data-product_sku="%s" data-quantity="1" class="%s button product_type_simple">%s</button>', esc_attr( $product->id ), esc_attr( $product->get_sku() ), esc_attr( $link['class'] ), esc_html( $link['label'] ) );
?>
</form>
<?php
} else {
echo apply_filters( 'woocommerce_loop_add_to_cart_link', sprintf('%s', esc_url( $link['url'] ), esc_attr( $product->id ), esc_attr( $product->get_sku() ), esc_attr( $link['class'] ), esc_attr( $product->product_type ), esc_html( $link['label'] ) ), $product, $link );
}
?>
<?php endif; ?>
And added this code to functions.php
function cs_wc_loop_add_to_cart_scripts() {
if ( is_shop() || is_product_category() || is_product_tag() || is_product() ) : ?>
<script>
jQuery(document).ready(function($) {
$(document).on( 'change', '.quantity .qty', function() {
$(this).parent('.quantity').next('.add_to_cart_button').attr('data-quantity', $(this).val());
});
});
</script>
<?php endif;
}
add_action( 'wp_footer', 'cs_wc_loop_add_to_cart_scripts' );
That fixes the issue with multiples being added, but now the shop returns to the top of the page to display the add to cart message when you add something to the basket. How can I keep it so that the navigation stays in the current location so the customer does not have to scroll down again?