On WooCommerce, I would like to change the Variable single product page layout. Because when you have an variable product you get this wired price rage (below product title) in the Variable Product page and it shows in the shop page as well.
For me, the standard way is to show the lowest price of the product in the shop as well as product page and change that price according to user selection of variables. I can't believe why.
I can remove the price range and show the lowest price using this code snippet.
https://businessbloomer.com/disable-variable-product-price-range-woocommerce/
But then again, that lowest price doesn't change according to select variables. There are again two prices in the variable product layout. This is my current variable product page layout
http://www.preorders.lk/product/beats-solo3-wireless-on-ear-headphones/
So, can anyone please help to remove the price range from the variable product page and show only one lowest price ( under the product title) of the product as default. So that price should be change according to the variables which that product have. And that lowest price should be show in the shop page as well.
Here's a screenshot:
2021 definitive update
Works for WooCommerce 4+ and 5+ available on:
Replace the Variable Price range by the chosen variation price in WooCommerce 4+
Update (December 2017): to avoid, Problems regarding non variable products in some themes and a repetition availability bug in some themes
Note: Some plugins like the German Market or some themes will not work with this code, as they make their own changes in the hooks or in the html structure.
This is completely possible.
First we remove the unwanted price.
We output instead the variable price without the price range and show the lowest price.
We make a copy of this variable price in a hidden container (to be used/read by our jQuery script)
Then we hide the containers of chosen variation price (and the stock availability)
With the help of our jQuery script, when we get the chosen variation price, we replace the variable price (and display the stock availability).
If the customer change of variation we update the price... If the variation price is not displayed during that change process, our variable price is displayed
Here is that code:
add_action( 'woocommerce_before_single_product', 'move_variations_single_price', 1 );
function move_variations_single_price(){
global $product, $post;
if ( $product->is_type( 'variable' ) ) {
// removing the variations price for variable products
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
// Change location and inserting back the variations price
add_action( 'woocommerce_single_product_summary', 'replace_variation_single_price', 10 );
}
}
function replace_variation_single_price(){
global $product;
// Main Price
$prices = array( $product->get_variation_price( 'min', true ), $product->get_variation_price( 'max', true ) );
$price = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
// Sale Price
$prices = array( $product->get_variation_regular_price( 'min', true ), $product->get_variation_regular_price( 'max', true ) );
sort( $prices );
$saleprice = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
if ( $price !== $saleprice && $product->is_on_sale() ) {
$price = '<del>' . $saleprice . $product->get_price_suffix() . '</del> <ins>' . $price . $product->get_price_suffix() . '</ins>';
}
?>
<style>
div.woocommerce-variation-price,
div.woocommerce-variation-availability,
div.hidden-variable-price {
height: 0px !important;
overflow:hidden;
position:relative;
line-height: 0px !important;
font-size: 0% !important;
}
</style>
<script>
jQuery(document).ready(function($) {
$('select').blur( function(){
if( '' != $('input.variation_id').val() ){
if($('p.availability'))
$('p.availability').remove();
$('p.price').html($('div.woocommerce-variation-price > span.price').html()).append('<p class="availability">'+$('div.woocommerce-variation-availability').html()+'</p>');
console.log($('input.variation_id').val());
} else {
$('p.price').html($('div.hidden-variable-price').html());
if($('p.availability'))
$('p.availability').remove();
console.log('NULL');
}
});
});
</script>
<?php
echo '<p class="price">'.$price.'</p>
<div class="hidden-variable-price" >'.$price.'</div>';
}
Code goes in any php file of your active child theme (or theme) or also in any plugin php file.
This code is tested and works on WooCommerce 3.2.x (should work on WooCommerce 2.6.x too)
You can optionally move the CSS (<style></style>) to the styles.css file of your active child theme (or active theme) and then remove it from this function…
Related:
Move the variation price location in WooCommerce
Late to the party but I was looking for a more dynamic/universal solution and less code so I adjusted the answer to the following.
The price is updated based on the variation-form triggers so the styling and original HTML is maintained.
add_action( 'woocommerce_before_single_product', 'move_variations_single_price', 1 );
function move_variations_single_price(){
global $product, $post;
if ( $product->is_type( 'variable' ) ) {
add_action( 'woocommerce_single_product_summary', 'replace_variation_single_price', 10 );
}
}
function replace_variation_single_price() {
?>
<style>
.woocommerce-variation-price {
display: none;
}
</style>
<script>
jQuery(document).ready(function($) {
var priceselector = '.product p.price';
var originalprice = $(priceselector).html();
$( document ).on('show_variation', function() {
$(priceselector).html($('.single_variation .woocommerce-variation-price').html());
});
$( document ).on('hide_variation', function() {
$(priceselector).html(originalprice);
});
});
</script>
<?php
}
Successfully tested with v4.0.1. As long as themes/plugins don't change the markup it should work. If not you can easily change the priceselector accordingly.
I'm aware that I am resurrecting an old thread here, but something I discovered when using this code is that you need to be aware that with this code as is you risk stopping single, non-variable prices from displaying on some themes as:
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
is triggered on all product pages, regardless of it being a variable product or not.
You can use the below version which simply checks if the current product is variable or not before running the rest of the code.
add_action( 'woocommerce_before_single_product', 'check_if_variable_first' );
function check_if_variable_first(){
if ( is_product() ) {
global $post;
$product = wc_get_product( $post->ID );
if ( $product->is_type( 'variable' ) ) {
// removing the price of variable products
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
// Change location of
add_action( 'woocommerce_single_product_summary', 'custom_wc_template_single_price', 10 );
function custom_wc_template_single_price(){
global $product;
// Variable product only
if($product->is_type('variable')):
// Main Price
$prices = array( $product->get_variation_price( 'min', true ), $product->get_variation_price( 'max', true ) );
$price = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
// Sale Price
$prices = array( $product->get_variation_regular_price( 'min', true ), $product->get_variation_regular_price( 'max', true ) );
sort( $prices );
$saleprice = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
if ( $price !== $saleprice && $product->is_on_sale() ) {
$price = '<del>' . $saleprice . $product->get_price_suffix() . '</del> <ins>' . $price . $product->get_price_suffix() . '</ins>';
}
?>
<style>
div.woocommerce-variation-price,
div.woocommerce-variation-availability,
div.hidden-variable-price {
height: 0px !important;
overflow:hidden;
position:relative;
line-height: 0px !important;
font-size: 0% !important;
}
</style>
<script>
jQuery(document).ready(function($) {
$('select').blur( function(){
if( '' != $('input.variation_id').val() ){
$('p.price').html($('div.woocommerce-variation-price > span.price').html()).append('<p class="availability">'+$('div.woocommerce-variation-availability').html()+'</p>');
console.log($('input.variation_id').val());
} else {
$('p.price').html($('div.hidden-variable-price').html());
if($('p.availability'))
$('p.availability').remove();
console.log('NULL');
}
});
});
</script>
<?php
echo '<p class="price">'.$price.'</p>
<div class="hidden-variable-price" >'.$price.'</div>';
endif;
}
}
}
}
Related
I do have a rather complex problem with price calculations in WooCommerce using the plugin GravityForms.
I do sell mostly customized products offering engraving options. Thats why I need GravityForms for.
I wanted to replace the standard woocommerce price by the chosen variable price below the heading. For that I used the very good solution made by
#Loictheaztec
Replace the variable price range by the chosen variation price
Here is his code I'am using in my functions.php
// Utility function to get the default variation (if it exist)
function get_default_variation( $product ){
$attributes_count = count($product->get_variation_attributes());
$default_attributes = $product->get_default_attributes();
// If no default variation exist we exit
if( $attributes_count != count($default_attributes) )
return false;
// Loop through available variations
foreach( $product->get_available_variations() as $variation ){
$found = true;
// Loop through variation attributes
foreach( $variation['attributes'] as $key => $value ){
$taxonomy = str_replace( 'attribute_', '', $key );
// Searching for a matching variation as default
if( isset($default_attributes[$taxonomy]) &&
$default_attributes[$taxonomy] != $value ){
$found = false;
break;
}
}
// If we get the default variation
if( $found ) {
$default_variaton = $variation;
break;
}
// If not we continue
else {
continue;
}
}
return isset($default_variaton) ? $default_variaton : false;
}
add_action( 'woocommerce_before_single_product',
'move_variations_single_price', 1 );
function move_variations_single_price(){
global $product, $post;
if ( $product->is_type( 'variable' ) ) {
// removing the variations price for variable products
remove_action( 'woocommerce_single_product_summary',
'woocommerce_template_single_price', 10 );
// Change location and inserting back the variations price
add_action( 'woocommerce_single_product_summary',
'replace_variation_single_price', 10 );
}
}
function replace_variation_single_price(){
global $product;
// Main Price
$prices = array( $product->get_variation_price( 'min', true ),
$product->get_variation_price( 'max', true ) );
$active_price = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s',
'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
// Sale Price
$prices = array( $product->get_variation_regular_price( 'min', true ),
$product->get_variation_regular_price( 'max', true ) );
sort( $prices );
$regular_price = $prices[0] !== $prices[1] ? sprintf( __( 'From:
%1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price(
$prices[0] );
if ( $active_price !== $regular_price && $product->is_on_sale() ) {
$price = '<del>' . $regular_price . $product->get_price_suffix() .
'</del> <ins>' . $active_price . $product->get_price_suffix() .
'</ins>';
} else {
$price = $regular_price;
}
// When a default variation is set for the variable product
if( get_default_variation( $product ) ) {
$default_variaton = get_default_variation( $product );
if( ! empty($default_variaton['price_html']) ){
$price_html = $default_variaton['price_html'];
} else {
if ( ! $product->is_on_sale() )
$price_html = $price =
wc_price($default_variaton['display_price']);
else
$price_html = $price;
}
$availiability = $default_variaton['availability_html'];
} else {
$price_html = $price;
$availiability = '';
}
// Styles ?>
<style>
div.woocommerce-variation-price,
div.woocommerce-variation-availability,
div.hidden-variable-price {
height: 0px !important;
overflow:hidden;
position:relative;
line-height: 0px !important;
font-size: 0% !important;
}
</style>
<?php // Jquery ?>
<script>
jQuery(document).ready(function($) {
var a = 'div.wc-availability', p = 'p.price';
$('select').blur( function(){
if( '' != $('input.variation_id').val() ){
if($(a).html() != '' ) $(a).html('');
$(p).html($('div.woocommerce-variation-price >
span.price').html());
$(a).html($('div.woocommerce-variation-
availability').html());
} else {
if($(a).html() != '' ) $(a).html('');
$(p).html($('div.hidden-variable-price').html());
}
});
});
</script>
<?php
echo '<p class="price">'.$price_html.'</p>
<div class="wc-availability">'.$availiability.'</div>
<div class="hidden-variable-price" >'.$price.'</div>';
}
Lets clarify a bit the things. Please see the screenshot to know where the woocommerce variations and the GravityForm fields are located.
The css class of the woocommerce price is:
`<p class="price">
<span class="woocommerce-Price-amount amount">45 </span>
<span class="woocommerce-Price-currencySymbol">€</span>
<span class="mwst"> inkl. MwSt.</span>
</p>`
And the css class of the GravityForms price is:
<li class="gfield">
<label class="gfield_label">Total</label>
<div class="ginput_container">
<span class="formattedTotalPrice ginput_total">45,00  €</span>
</div>
</li>
Now lets select a price variation from the woocommerce fields.
This outputs very nicely the selected variation price of woocommerce at top as well as on the bottom.
So now lets start the problem and select a variation price out of a GravityForms field.
As you can see the price on top won't recognize the price change. But the price displayed at the lower end shows it correctly.
The question is now, is it possible to modify the code which replaces the variable prices by chosen variation price in a way that it will recognize price changes made via GravityForms too?
Update
I've searched through the documentation of gravity forms to find a filter hook for the price label. And I have found this one:
GravityForms Documentation - gform_product_price Filter
Then I checked what happens if I use this function in the functions.php file of my child theme.
add_filter( 'gform_product_price', 'set_price_label', 10, 2 );
function set_price_label( ) {
echo 'Some output somewhere?';
}
or this function
add_filter( 'gform_product_price', 'set_price_label_test', 10, 2 );
function set_price_label_test( $sublabel, $form_id ) {
return 'Cost';
}
unfortunately nothing happened.
Here is an image of the result.
I'm have started building an e-shop in Wordepress with WooCommerce plugin.
I added some products with variations and I noticed that the price is displayed after attributes select fields.
Is it possible to move the price between Title and short description as for simple products?
The url of one product is:
http://www.roubinisideas.com/test2/product/uncategorized/vintage/
Update (on September 2019):
Avoiding availability repetitions (bug solved on 2018)
Keep other product types unchanged (2019)
This is possible and it's is based on this answer that I have made:
Here I have updated the jQuery code to take into account when a variation is set by default for a variable product.
Here is the code:
add_action( 'woocommerce_single_product_summary', 'move_single_product_variable_price_location', 2 );
function move_single_product_variable_price_location() {
global $product;
// Variable product only
if( $product->is_type('variable') ):
// removing the price of variable products
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
// Add back the relocated (customized) price of variable products
add_action( 'woocommerce_single_product_summary', 'custom_single_product_variable_prices', 10 );
endif;
}
function custom_single_product_variable_prices(){
global $product;
// Main Price
$prices = array( $product->get_variation_price( 'min', true ), $product->get_variation_price( 'max', true ) );
$price = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
// Sale Price
$prices = array( $product->get_variation_regular_price( 'min', true ), $product->get_variation_regular_price( 'max', true ) );
sort( $prices );
$saleprice = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
if ( $price !== $saleprice && $product->is_on_sale() ) {
$price = '<del>' . $saleprice . $product->get_price_suffix() . '</del> <ins>' . $price . $product->get_price_suffix() . '</ins>';
}
?>
<style>
div.woocommerce-variation-price,
div.woocommerce-variation-availability,
div.hidden-variable-price {
height: 0px !important;
overflow:hidden;
position:relative;
line-height: 0px !important;
font-size: 0% !important;
visibility: hidden !important;
}
</style>
<script>
jQuery(document).ready(function($) {
// When variable price is selected by default
setTimeout( function(){
if( 0 < $('input.variation_id').val() && null != $('input.variation_id').val() ){
if($('p.availability'))
$('p.availability').remove();
$('p.price').html($('div.woocommerce-variation-price > span.price').html()).append('<p class="availability">'+$('div.woocommerce-variation-availability').html()+'</p>');
console.log($('div.woocommerce-variation-availability').html());
}
}, 300 );
// On live variation selection
$('select').blur( function(){
if( 0 < $('input.variation_id').val() && null != $('input.variation_id').val() ){
if($('.price p.availability') || $('.price p.stock') )
$('p.price p').each(function() {
$(this).remove();
});
$('p.price').html($('div.woocommerce-variation-price > span.price').html()).append('<p class="availability">'+$('div.woocommerce-variation-availability').html()+'</p>');
console.log($('input.variation_id').val());
} else {
$('p.price').html($('div.hidden-variable-price').html());
if($('p.availability'))
$('p.availability').remove();
console.log('NULL');
}
});
});
</script>
<?php
echo '<p class="price">'.$price.'</p>
<div class="hidden-variable-price" >'.$price.'</div>';
}
Code goes in any php file of your active child theme (or theme) or also in any plugin php file.
This code is tested and works on WooCommerce 3+ (should work on WooCommerce 2.6.x too)
related: Replace the Variable Price range by the chosen variation price in WooCommerce 3
I'm experiencing the following bug on a clients WooCommerce website. We use this free Variations Swatch for Woocommerce plugin. I have a variable product with 4 different colors.
If all colors are sold out, when selecting a variation the "out of stock" custom message is shown. But when selecting a different variation the message is shown again, so there are now 2 blocks with "out of stock" custom message:
I have a different product in this store with color and engine variations and there's no issue like this.
Question:
How can I make the out of stock custom message to be shown only once at the same time?
Here is the website live link to the product page, where the issue can be seen.
This is my code in the functions.php file of my theme:
// Change location of
add_action( 'woocommerce_single_product_summary', 'custom_wc_template_single_price', 10 );
function custom_wc_template_single_price(){
global $product;
// Variable product only
if($product->is_type('variable')):
// Main Price
$prices = array( $product->get_variation_price( 'min', true ), $product->get_variation_price( 'max', true ) );
$price = $prices[0] !== $prices[1] ? sprintf( __( 'Ab: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
// Sale Price
$prices = array( $product->get_variation_regular_price( 'min', true ), $product->get_variation_regular_price( 'max', true ) );
sort( $prices );
$saleprice = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
if ( $price !== $saleprice && $product->is_on_sale() ) {
$price = '<del>' . $saleprice . $product->get_price_suffix() . '</del> <ins>' . $price . $product->get_price_suffix() . '</ins>';
}
?>
<style>
div.woocommerce-variation-price,
div.woocommerce-variation-availability,
div.hidden-variable-price {
height: 0px !important;
overflow:hidden;
position:relative;
line-height: 0px !important;
font-size: 0% !important;
}
</style>
<script>
jQuery(document).ready(function($) {
$('select').blur( function(){
if( '' != $('input.variation_id').val() ){
if($('p.availability')) $('p.availability').remove();
$('p.price').html($('div.woocommerce-variation-price > span.price').html()).append('<p class="availability">'+$('div.woocommerce-variation-availability').html()+'</p>');
console.log($('input.variation_id').val());
} else {
$('p.price').html($('div.hidden-variable-price').html());
if($('p.availability'))
$('p.availability').remove();
console.log('NULL');
}
});
});
</script>
<?php
echo '<p class="price">'.$price.'</p>
<div class="hidden-variable-price" >'.$price.'</div>';
endif;
}
// This filter for custom in stock and out of stock messages:
add_filter( 'woocommerce_get_availability', 'wcs_custom_get_availability', 1, 2);
function wcs_custom_get_availability( $availability, $_product ) {
// Change In Stock Text
if ( $_product->is_in_stock() ) {
$availability['availability'] = __('Dein Minimoto Produkt ist verfügbar!', 'woocommerce');
}
// Change Out of Stock Text
if ( ! $_product->is_in_stock() ) {
$availability['availability'] = __('Aktuell nicht vorrätig, bitte kontaktieren Sie uns telefonisch unter +49 403 486 2392', 'woocommerce');
}
return $availability;
}
Update: I have changed in your code:
'<p class="availability">+$('div.woocommerce-variation-availability').html()+</p>'
To:
'<div class="availability">+$('div.woocommerce-variation-availability').html()+</div>'
Avoiding repetitive malformed html <p> and </p> tags…
And changed:
if($('p.availability')) $('p.availability').remove();
To this better one:
if($('div.availability').html() != undefined ) $('div.availability').remove();
I have simplified the code in your wcs_custom_get_availability() function too…
So the correct code should be:
add_filter( 'woocommerce_get_availability', 'wcs_custom_get_availability', 1, 2);
function wcs_custom_get_availability( $availability, $product ) {
// Change In Stock Text
if ( $product->is_in_stock() )
$availability['availability'] = __('Dein Minimoto Produkt ist verfügbar!', 'woocommerce');
else
$availability['availability'] = __('Aktuell nicht vorrätig, bitte kontaktieren Sie uns telefonisch unter +49 403 486 2392', 'woocommerce');
return $availability;
}
// Change location of
add_action( 'woocommerce_single_product_summary', 'custom_wc_template_single_price', 10 );
function custom_wc_template_single_price(){
global $product;
// Variable product only
if($product->is_type('variable')):
// Main Price
$prices = array( $product->get_variation_price( 'min', true ), $product->get_variation_price( 'max', true ) );
$price = $prices[0] !== $prices[1] ? sprintf( __( 'Ab: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
// Sale Price
$prices = array( $product->get_variation_regular_price( 'min', true ), $product->get_variation_regular_price( 'max', true ) );
sort( $prices );
$saleprice = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
if ( $price !== $saleprice && $product->is_on_sale() ) {
$price = '<del>' . $saleprice . $product->get_price_suffix() . '</del> <ins>' . $price . $product->get_price_suffix() . '</ins>';
}
?>
<style>
div.woocommerce-variation-price,
div.woocommerce-variation-availability,
div.hidden-variable-price {
height: 0px !important;
overflow:hidden;
position:relative;
line-height: 0px !important;
font-size: 0% !important;
}
</style>
<script>
jQuery(document).ready(function($) {
$('select').blur( function(){
var availability = '<div class="availability">'+$('div.woocommerce-variation-availability').html()+'</div>';
if( '' != $('input.variation_id').val() ){
if($('div.availability').html() != undefined ) $('div.availability').remove(); // Just in case
$('p.price').html($('div.woocommerce-variation-price > span.price').html()).append(availability);
console.log('IF - '+$('input.variation_id').val());
} else {
$('p.price').html($('div.hidden-variable-price').html());
if($('div.availability').html() != undefined ) $('div.availability').remove();
console.log('ELSE');
}
});
});
</script>
<?php
echo '<p class="price">'.$price.'</p>
<div class="hidden-variable-price" >'.$price.'</div>';
endif;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and work … This should solve your issue.
This row tells you everything
$('p.price').html($('div.woocommerce-variation-price > span.price').html()).append('<p class="availability">'+$('div.woocommerce-variation-availability').html()+'</p>');
you are using append not html()
change your code to:
$('p.price').html($('div.woocommerce-variation-price > span.price').html()+'<p class="availability">'+$('div.woocommerce-variation-availability').html()+'</p>');
On WooCommerce, I would like to change the Variable single product page layout. Because when you have an variable product you get this wired price rage (below product title) in the Variable Product page and it shows in the shop page as well.
For me, the standard way is to show the lowest price of the product in the shop as well as product page and change that price according to user selection of variables. I can't believe why.
I can remove the price range and show the lowest price using this code snippet.
https://businessbloomer.com/disable-variable-product-price-range-woocommerce/
But then again, that lowest price doesn't change according to select variables. There are again two prices in the variable product layout. This is my current variable product page layout
http://www.preorders.lk/product/beats-solo3-wireless-on-ear-headphones/
So, can anyone please help to remove the price range from the variable product page and show only one lowest price ( under the product title) of the product as default. So that price should be change according to the variables which that product have. And that lowest price should be show in the shop page as well.
Here's a screenshot:
2021 definitive update
Works for WooCommerce 4+ and 5+ available on:
Replace the Variable Price range by the chosen variation price in WooCommerce 4+
Update (December 2017): to avoid, Problems regarding non variable products in some themes and a repetition availability bug in some themes
Note: Some plugins like the German Market or some themes will not work with this code, as they make their own changes in the hooks or in the html structure.
This is completely possible.
First we remove the unwanted price.
We output instead the variable price without the price range and show the lowest price.
We make a copy of this variable price in a hidden container (to be used/read by our jQuery script)
Then we hide the containers of chosen variation price (and the stock availability)
With the help of our jQuery script, when we get the chosen variation price, we replace the variable price (and display the stock availability).
If the customer change of variation we update the price... If the variation price is not displayed during that change process, our variable price is displayed
Here is that code:
add_action( 'woocommerce_before_single_product', 'move_variations_single_price', 1 );
function move_variations_single_price(){
global $product, $post;
if ( $product->is_type( 'variable' ) ) {
// removing the variations price for variable products
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
// Change location and inserting back the variations price
add_action( 'woocommerce_single_product_summary', 'replace_variation_single_price', 10 );
}
}
function replace_variation_single_price(){
global $product;
// Main Price
$prices = array( $product->get_variation_price( 'min', true ), $product->get_variation_price( 'max', true ) );
$price = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
// Sale Price
$prices = array( $product->get_variation_regular_price( 'min', true ), $product->get_variation_regular_price( 'max', true ) );
sort( $prices );
$saleprice = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
if ( $price !== $saleprice && $product->is_on_sale() ) {
$price = '<del>' . $saleprice . $product->get_price_suffix() . '</del> <ins>' . $price . $product->get_price_suffix() . '</ins>';
}
?>
<style>
div.woocommerce-variation-price,
div.woocommerce-variation-availability,
div.hidden-variable-price {
height: 0px !important;
overflow:hidden;
position:relative;
line-height: 0px !important;
font-size: 0% !important;
}
</style>
<script>
jQuery(document).ready(function($) {
$('select').blur( function(){
if( '' != $('input.variation_id').val() ){
if($('p.availability'))
$('p.availability').remove();
$('p.price').html($('div.woocommerce-variation-price > span.price').html()).append('<p class="availability">'+$('div.woocommerce-variation-availability').html()+'</p>');
console.log($('input.variation_id').val());
} else {
$('p.price').html($('div.hidden-variable-price').html());
if($('p.availability'))
$('p.availability').remove();
console.log('NULL');
}
});
});
</script>
<?php
echo '<p class="price">'.$price.'</p>
<div class="hidden-variable-price" >'.$price.'</div>';
}
Code goes in any php file of your active child theme (or theme) or also in any plugin php file.
This code is tested and works on WooCommerce 3.2.x (should work on WooCommerce 2.6.x too)
You can optionally move the CSS (<style></style>) to the styles.css file of your active child theme (or active theme) and then remove it from this function…
Related:
Move the variation price location in WooCommerce
Late to the party but I was looking for a more dynamic/universal solution and less code so I adjusted the answer to the following.
The price is updated based on the variation-form triggers so the styling and original HTML is maintained.
add_action( 'woocommerce_before_single_product', 'move_variations_single_price', 1 );
function move_variations_single_price(){
global $product, $post;
if ( $product->is_type( 'variable' ) ) {
add_action( 'woocommerce_single_product_summary', 'replace_variation_single_price', 10 );
}
}
function replace_variation_single_price() {
?>
<style>
.woocommerce-variation-price {
display: none;
}
</style>
<script>
jQuery(document).ready(function($) {
var priceselector = '.product p.price';
var originalprice = $(priceselector).html();
$( document ).on('show_variation', function() {
$(priceselector).html($('.single_variation .woocommerce-variation-price').html());
});
$( document ).on('hide_variation', function() {
$(priceselector).html(originalprice);
});
});
</script>
<?php
}
Successfully tested with v4.0.1. As long as themes/plugins don't change the markup it should work. If not you can easily change the priceselector accordingly.
I'm aware that I am resurrecting an old thread here, but something I discovered when using this code is that you need to be aware that with this code as is you risk stopping single, non-variable prices from displaying on some themes as:
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
is triggered on all product pages, regardless of it being a variable product or not.
You can use the below version which simply checks if the current product is variable or not before running the rest of the code.
add_action( 'woocommerce_before_single_product', 'check_if_variable_first' );
function check_if_variable_first(){
if ( is_product() ) {
global $post;
$product = wc_get_product( $post->ID );
if ( $product->is_type( 'variable' ) ) {
// removing the price of variable products
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
// Change location of
add_action( 'woocommerce_single_product_summary', 'custom_wc_template_single_price', 10 );
function custom_wc_template_single_price(){
global $product;
// Variable product only
if($product->is_type('variable')):
// Main Price
$prices = array( $product->get_variation_price( 'min', true ), $product->get_variation_price( 'max', true ) );
$price = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
// Sale Price
$prices = array( $product->get_variation_regular_price( 'min', true ), $product->get_variation_regular_price( 'max', true ) );
sort( $prices );
$saleprice = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
if ( $price !== $saleprice && $product->is_on_sale() ) {
$price = '<del>' . $saleprice . $product->get_price_suffix() . '</del> <ins>' . $price . $product->get_price_suffix() . '</ins>';
}
?>
<style>
div.woocommerce-variation-price,
div.woocommerce-variation-availability,
div.hidden-variable-price {
height: 0px !important;
overflow:hidden;
position:relative;
line-height: 0px !important;
font-size: 0% !important;
}
</style>
<script>
jQuery(document).ready(function($) {
$('select').blur( function(){
if( '' != $('input.variation_id').val() ){
$('p.price').html($('div.woocommerce-variation-price > span.price').html()).append('<p class="availability">'+$('div.woocommerce-variation-availability').html()+'</p>');
console.log($('input.variation_id').val());
} else {
$('p.price').html($('div.hidden-variable-price').html());
if($('p.availability'))
$('p.availability').remove();
console.log('NULL');
}
});
});
</script>
<?php
echo '<p class="price">'.$price.'</p>
<div class="hidden-variable-price" >'.$price.'</div>';
endif;
}
}
}
}
I have been searching for this for quite a while now and i can't find any solutions.
I am looking for a way to display the products variation prices inside the "From:" price field, in order to have only 1 price shown on the product page.
I have tried this:
function woocommerce_template_single_price() {
global $product;
if ( ! $product->is_type('variable') ) {
woocommerce_get_template( 'single-product/price.php' );
}}
But it doesn't work for me, The price should change dynamicaly when a different product variation is selected. Any ideas?
add_action( 'woocommerce_before_single_product', 'check_if_variable_first' );
function check_if_variable_first(){
if ( is_product() ) {
global $post;
$product = wc_get_product( $post->ID );
if ( $product->is_type( 'variable' ) ) {
// removing the price of variable products
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
// Change location of
add_action( 'woocommerce_single_product_summary', 'custom_wc_template_single_price', 10 );
function custom_wc_template_single_price(){
global $product;
// Variable product only
if($product->is_type('variable')):
// Main Price
$prices = array( $product->get_variation_price( 'min', true ), $product->get_variation_price( 'max', true ) );
$price = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
// Sale Price
$prices = array( $product->get_variation_regular_price( 'min', true ), $product->get_variation_regular_price( 'max', true ) );
sort( $prices );
$saleprice = $prices[0] !== $prices[1] ? sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
if ( $price !== $saleprice && $product->is_on_sale() ) {
$price = '<del>' . $saleprice . $product->get_price_suffix() . '</del> <ins>' . $price . $product->get_price_suffix() . '</ins>';
}
?>
<style>
div.woocommerce-variation-price,
div.woocommerce-variation-availability,
div.hidden-variable-price {
height: 0px !important;
overflow:hidden;
position:relative;
line-height: 0px !important;
font-size: 0% !important;
}
</style>
<script>
jQuery(document).ready(function($) {
$('select').blur( function(){
if( '' != $('input.variation_id').val() ){
$('p.price').html($('div.woocommerce-variation-price > span.price').html()).append('<p class="availability">'+$('div.woocommerce-variation-availability').html()+'</p>');
console.log($('input.variation_id').val());
} else {
$('p.price').html($('div.hidden-variable-price').html());
if($('p.availability'))
$('p.availability').remove();
console.log('NULL');
}
});
});
</script>
<?php
echo '<p class="price">'.$price.'</p>
<div class="hidden-variable-price" >'.$price.'</div>';
endif;
}
}
}
}