How to add a string like "Price from" next to configurable product prices on Category, Search and Product pages, but only if the configurable product has simple products with different prices in it?
-
1Not trying to be harsh but there is a very similar example in Magento 2 Developer documentation devdocs.magento.com/guides/v2.0/extension-dev-guide/… I strongly recommend you having a go with this.– Alvin NguyenCommented Jan 30, 2018 at 22:28
-
1Not sure what the down votes or close votes are about, it's a legitimate question on how to improve configurable products in Magento 2. @AlvinNguyen I haven't done enough research yet, but it doesn't seem to be that simple to target only configurable products...– LezCommented Jan 30, 2018 at 22:55
-
I've dowvoted too. You say "I haven't done enough research" and tooltips for up/downvotes says "This questions shows research effort ...." or not. So please spent your time first, before asking others. If not possible add a "better" description, that would help too. (and finally it was reopened after description edits)– sv3nCommented Feb 3, 2018 at 21:04
-
1I disagree that you need to research thoroughly before asking. Stackexchange is about sharing knowledge and expertise. My question was simple and to the point (in it's original form) and it's definitely useful to improve configurable products. Also it was reopened because I flaged it for a mod (because it was closed as "off topic"). I made the edits afterwards when I figured out all the stuff that needed to be adjusted to make this more customer-friendly.– LezCommented Feb 4, 2018 at 11:43
-
3I have UPvoted the question because it actually made sense, and if someone is not able to understand the question they should comment rather than downvoting. Plus the comment from sv3n is not justified. The community is just being a market to gain reputation by up/down voting rather than sharing knowledge.– GaganCommented May 2, 2018 at 4:39
1 Answer
I did this by extending Magento\ConfigurableProduct\Pricing\Price\FinalPrice
with functions for getting min/max final price of configurable products and inserting the label only when needed (when there are simple products with different prices inside the configurable).
Gonna post my solution for others that might need help with this:
{Vendor}/{Module}/etc/di.xml
<preference for="Magento\ConfigurableProduct\Pricing\Price\FinalPrice" type="{Vendor}\{Module}\Pricing\Price\FinalPrice"/>
{Vendor}/{Module}/Pricing/Price/FinalPrice
<?php
namespace Vendor\Module\Pricing\Price;
use Magento\Framework\App\ObjectManager;
class FinalPrice extends \Magento\ConfigurableProduct\Pricing\Price\FinalPrice
{
protected $priceResolver;
protected $maxFinalAmount;
protected $minFinalAmount;
protected $lowestPriceOptionsProvider;
protected $configurableType;
public function __construct(
\Magento\Framework\Pricing\SaleableInterface $saleableItem,
$quantity,
\Magento\Framework\Pricing\Adjustment\CalculatorInterface $calculator,
\Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency,
\Magento\ConfigurableProduct\Pricing\Price\PriceResolverInterface $priceResolver,
\Magento\ConfigurableProduct\Pricing\Price\LowestPriceOptionsProviderInterface $lowestPriceOptionsProvider = null,
\Magento\ConfigurableProduct\Model\Product\Type\Configurable $configurableType
) {
parent::__construct($saleableItem, $quantity, $calculator, $priceCurrency, $priceResolver);
$this->priceResolver = $priceResolver;
$this->lowestPriceOptionsProvider = $lowestPriceOptionsProvider ?:
ObjectManager::getInstance()->get(\Magento\ConfigurableProduct\Pricing\Price\LowestPriceOptionsProviderInterface::class);
$this->configurableType = $configurableType ?:
ObjectManager::getInstance()->get(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::class);
}
public function getMaxFinalAmount()
{
if (null === $this->maxFinalAmount) {
$this->maxFinalAmount = $this->doGetMaxFinalAmount() ?: false;
}
return $this->maxFinalAmount;
}
protected function doGetMaxFinalAmount()
{
$maxAmount = null;
$usedProducts = $this->configurableType->getUsedProducts($this->product);
foreach ($usedProducts as $product) {
$childPriceAmount = $product->getPriceInfo()->getPrice('final_price')->getAmount();
if (!$maxAmount || ($childPriceAmount->getValue() > $maxAmount->getValue())) {
$maxAmount = $childPriceAmount;
}
}
return $maxAmount;
}
public function getMinFinalAmount()
{
if (null === $this->minFinalAmount) {
$this->minFinalAmount = $this->doGetMinFinalAmount() ?: parent::getAmount();
}
return $this->minFinalAmount;
}
protected function doGetMinFinalAmount()
{
$minAmount = null;
$usedProducts = $this->lowestPriceOptionsProvider->getProducts($this->product);
foreach ($usedProducts as $product) {
$childPriceAmount = $product->getPriceInfo()->getPrice('final_price')->getAmount();
if (!$minAmount || ($childPriceAmount->getValue() < $minAmount->getValue())) {
$minAmount = $childPriceAmount;
}
}
return $minAmount;
}
}
Then you can call the new function getMinFinalAmount
and getMaxFinalAmount
from your custom:
.../Magento_ConfigurableProduct/templates/product/price/final_price.phtml
$minAmount = $finalPriceModel->getMinFinalAmount();
$maxAmount = $finalPriceModel->getMaxFinalAmount();
And display the label where you want like this:
<?php if ($minAmount < $maxAmount) { ?>
<span class="price-label"><?php echo __('Price from:') ?></span>
<?php } ?>
All that's left is to use JS to hide the Price from
label when a simple configuration is selected.
That depends on if you're using swatches or not.
To remove the label by using swatches, you need to edit Magento_Swatches/web/js/swatch-renderer.js
.
I added this code to the _UpdatePrice
function which is executed when a swatch is clicked.
$product.find('.price-label').hide(0);
To remove the label by using ordinary configurable options, you need to edit Magento_ConfigurableProduct/web/js/configurable.js
.
I added this code to the _calculatePrice
function which is executed when a configurable option is selected from the dropdown.
$(this.options.priceHolderSelector).find('.price-label').hide(0);