I am trying to change the position of the Product Variations inside the Single Product Page. Right now, they appear under the Short Description but I want them to appear before the Product's Short Description, right after the product Title and Price.
The code I have for the moment is the following:
function move_linked_variation_options()
{
remove_action('woocommerce_variable_add_to_cart', 'woocommerce_variable_add_to_cart', 30);
add_action('woocommerce_single_product_summary', 'woocommerce_variable_add_to_cart', 10);
}
add_action('init', 'move_linked_variation_options');
It works great when products have variations, but when I navigate to a product that has no variations, it just throws an error which is the following:
Do you have any idea why this is happening?
Should I have some kind of conditional inside the function?
Am I missing any action before the position change?
Any help will be appreciated.
Hope this helps
add_action( 'woocommerce_before_single_product_summary', 'move_linked_variation_options' );
function move_linked_variation_options() {
global $product;
if ( $product->is_type( 'variable' ) ) {
remove_action( 'woocommerce_variable_add_to_cart', 'woocommerce_variable_add_to_cart', 30 );
add_action( 'woocommerce_single_product_summary', 'woocommerce_variable_add_to_cart', 10 );
}
}
Related
Im trying to hide the add to cart button in woocommerce for all products except a varibale product i have. I have tried the following which leaves the variable select options (which is what i want) but it hides the add to cart button (which i don't want).
add_filter( 'woocommerce_is_purchasable', '__return_false' );
add_action( 'woocommerce_single_product_summary', 'hide_add_to_cart_button_variable_product', 1, 0 );
function hide_add_to_cart_button_variable_product() {
remove_action( 'woocommerce_single_variation', 'woocommerce_single_variation_add_to_cart_button', 20);
}
Is there a way to do this?
All my products are simple products except for this single variable products, so maybe there is a function to hide the cart button for all simples except variables?
add_action('woocommerce_single_product_summary', 'wp66176371_remove_product_description_add_cart_button', 1 );
function wp66176371_remove_product_description_add_cart_button() {
global $product;
if ( !empty($product) && $product->is_type( 'simple' ) ) {
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
}
}
I think you can just edit the simple.php template file in the add-to-cart directory so it wouldn't show the button for simple products.
as the title states, I'm trying to remove the buy button for virtual products. I am using the Astra theme in WordPress alongside Woocommerce, and Elementor.
Now my issue is that with my current implementation, it does remove the button from the individual product page. However it still displays the button on the categories page, which is a pain. I have tried setting the price to nothing, and while that does work. It doesn't help as I still want the products to have their prices listed.
I have added the following code to the functions.php section of my duplicated theme file;
function buy_filter()
{
if ( ! is_product() ) return;
$product = get_product();
if ($product->is_virtual('yes'))
{
//$product->is_purchasable('false')
//remove_action( 'woocommerce_before_shop_loop', 'woocommerce_result_count', 20 );
//remove_action('woocommerce_before_shop_loop', 'woocommerce_catalog_ordering', 30);
remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart' );
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30);
remove_action( 'woocommerce_simple_add_to_cart', 'woocommerce_simple_add_to_cart', 30);
remove_action( 'woocommerce_grouped_add_to_cart', 'woocommerce_grouped_add_to_cart', 30);
remove_action( 'woocommerce_variable_add_to_cart', 'woocommerce_variable_add_to_cart', 30);
remove_action( 'woocommerce_external_add_to_cart', 'woocommerce_external_add_to_cart', 30);
}
}
add_action ('wp', 'buy_filter');
Any help would be greatly appreciated, and I'm happy to give any more details I can to aid in the matter.
Thank you kindly!
You need to get the specific product by it's ID, I have modified a few part of your code and removed few of the hooks you used. Please add those if required.
function woocommerce_remove_cart()
{
if ( ! is_product() ) return;
$product_id=get_the_ID();
$product = wc_get_product($product_id);
if ($product->is_virtual('yes'))
{
remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
}
}//end of function
add_action('wp_head','woocommerce_remove_cart');
Hope it works.
add_filter( 'woocommerce_is_purchasable', 'woocommerce_isproduct_purchasable', 10, 2 );
function woocommerce_isproduct_purchasable( $purchasable, $product ) {
return ($product->is_virtual( 'yes' ) ) ? false : $purchasable;
}
This is the hook you are looking for
I want to add a custom field on product cards like below. The code I wrote for this works, but the custom field I added appears above the category name.
I want it to appear between the stars and the product name as I showed in the picture.
The code I am currently using for this is
add_action( 'woocommerce_after_shop_loop_item_title', 'woo_show_product_id', 20);
function woo_show_product_id() {
global $product;
echo $product->id;
}
How can I do that or what adjustment is needed for this?
In includes/wc-template-hooks.php we can find:
add_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_rating', 5 );
So change priority from 20
add_action( 'woocommerce_after_shop_loop_item_title', 'woo_show_product_id', 20);
To 4 to display your custom field just before the star ratings
add_action( 'woocommerce_after_shop_loop_item_title', 'woo_show_product_id', 4 );
Priority: Used to specify the order in which the functions associated with a particular action are executed. Lower numbers correspond with earlier execution, and functions with the same priority are executed in the order in which they were added to the action. Default value: 10
Note: use $product->get_id(); as of WooCommerce 3.0
So to answer your question, you can use
via woocommerce_after_shop_loop_item_title
function woo_show_product_id() {
global $product;
// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
// Get Product ID
echo $product->get_id();
}
}
add_action( 'woocommerce_after_shop_loop_item_title', 'woo_show_product_id', 4 );
OR
some other hook from includes/wc-template-hooks.php
add_action( 'woocommerce_shop_loop_item_title', 'woocommerce_template_loop_product_title', 10 );
And then you get with priority 11
via woocommerce_shop_loop_item_title
function woo_show_product_id() {
global $product;
// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
// Get Product ID
echo $product->get_id();
}
}
add_action( 'woocommerce_shop_loop_item_title', 'woo_show_product_id', 11 );
I am using this function to add a variation and quantity fields to my archive pages-
add_action( 'woocommerce_before_shop_loop', 'my_select_variations' );
function my_select_variations() {
remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
I am then removing the price range from all pages using this-
add_filter( 'woocommerce_variable_sale_price_html', 'my_remove_variation_price', 10, 2 );
add_filter( 'woocommerce_variable_price_html', 'my_remove_variation_price', 10, 2 );
function my_remove_variation_price( $price ) {
$price = '';
return $price;
}
This works well, however I am not satisfied with the order of the files for my variation products. How can I change the order of the variation price so that it is above the drop down box, as illustrated here? Is there a simple way to do this through the I better off using jQuery to relocate the price?
EDIT: Using the below I have moved the price on single product pages, but not on archive pages yet.
remove_action( 'woocommerce_single_variation', 'woocommerce_single_variation', 10 );
add_action( 'woocommerce_before_variations_form', 'woocommerce_single_variation', 10 );
In my WooCommerce shop I want to hide the prices until the customer has logged in. I've got the following code working that does exactly that:
add_action('init','hide_price');
function hide_price(){
if(!is_user_logged_in()){
remove_action('woocommerce_after_shop_loop_item','woocommerce_template_loop_add_to_cart',10);
remove_action('woocommerce_single_product_summary','woocommerce_template_single_add_to_cart',30);
remove_action('woocommerce_single_product_summary','woocommerce_template_single_price',10);
remove_action('woocommerce_after_shop_loop_item_title','woocommerce_template_loop_price',10);
add_action('woocommerce_single_product_summary','print_login_to_see',31);
add_action('woocommerce_after_shop_loop_item','print_login_to_see',11);
}
}
function print_login_to_see(){
echo '' . __('Login to see prices','theme_name') . '';
}
However this also removes the variation drop down and I would like to keep that.
Is there any direct way to keep the variation drop down menu but still hide the prices until the customer has logged in?
Thanks
Updated:
You will need to separate shop and archives pages from single product pages. In single product pages you will target variable products to add and remove the specific hooked functions.
Last thing, in your function print_login_to_see(), woocommerce_get_page_id() is obsolete and it's replaced by wc_get_page_id() …
So your code will look to this:
// For product archives pages
add_action( 'init', 'hide_product_archives_prices' );
function hide_product_archives_prices(){
if( is_user_logged_in() ) return;
remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
remove_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_price', 10) ;
add_action ( 'woocommerce_after_shop_loop_item', 'print_login_to_see', 10 );
}
//
add_action( 'woocommerce_single_product_summary', 'hide_single_product_prices', 1 );
function hide_single_product_prices(){
if( is_user_logged_in() ) return;
global $product;
remove_action('woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
if( ! $product->is_type('variable') ){
remove_action('woocommerce_single_product_summary','woocommerce_template_single_add_to_cart', 30 );
add_action( 'woocommerce_single_product_summary','print_login_to_see', 30 );
} else {
remove_action( 'woocommerce_single_variation', 'woocommerce_single_variation', 10);
remove_action( 'woocommerce_single_variation', 'woocommerce_single_variation_add_to_cart_button', 20 );
add_action( 'woocommerce_single_variation', 'print_login_to_see', 20 );
}
}
// Display a my account link
function print_login_to_see(){
echo '' . __('Login to see prices','theme_name') . '';
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested on WooCommerce 3+ and works.