I have researched the way Magento goes about to calculate the price of the product. It is complicated and it is unnecessary to recreate that entire process just for the sake of displaying the total price. So I have made an approach which may seem dirty and quick, but you can achieve solution to your problem.
I took the approach of injecting a custom javascript file to every product page and simply using the DOM Manipulation to achieve the result.
Read the answer to the end and implement the solution.
The first step is to create the following files and folders in order to implement the solution.
In your theme folder create
Magento_Catalog/layout/catalog_product_view.xml
Magento_Catalog/templates/product/customjs.phtml
The content for catalog_product_view.xml
is
<page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<referenceContainer name="content">
<block class="Magento\Framework\View\Element\Template"
name="custom.js" as="custom.js"
template="Magento_Catalog::product/customjs.phtml"/>
</referenceContainer>
</page>
The content for customjs.phtml
is
<script>// <![CDATA[
require([
'jquery',
'hello'
], function ($) {
$('.product-info-main').changePrice();
});
// ]]>
</script>
Now go on and create Vendorname/Themename/web/js/custom.js
and the content is
define('jquery', function($) {
var priceDomain = "";
$.fn.changePrice = function(){
try{
const theElements = document.getElementsByClassName("price-notice");
const productPrice = parseFloat(removeSpaceFromMainPrice(document.getElementsByClassName("price")[0].innerText));
for(let i=0;i<theElements.length;i++){
theElements[i].innerText = generateText((parseFloat(removeSpaceFromCustomPrice(theElements[i].innerText)) + productPrice));
}
}
catch (e) {
console.log(e);
}
}
let removeSpaceFromMainPrice = function (price) {
priceDomain = ""+price.charAt(0);
return price.substr(1);
}
let removeSpaceFromCustomPrice = function (price) {
return price.substr(3);
}
let generateText = function (price) {
return " will cost you a total of "+priceDomain+" "+parseFloat(price).toFixed(2);
}
}(jQuery)
);
Then create the Vendorname\Themename\requirejs-config.js
and the content is
var config = {
map: {
'*' : {
'hello' : 'js/custom'
}
}
}
Now go on and deploy the static content and clear the cache to see the effect.
Note:
- This way of doing it has it's drawbacks. For instance, the above method only works for simple product that has radio buttons as custom options. Also, if MSRP is applied the above code won't work. But don't worry as long as you know how to error handle and do DOM manipulation you can add the code and make it work.
- Keep in mind that this is just a boilerplate code and customise this code to suit your needs.
This piece of code can be further improved and if there is any other way to achieve this then the answers are welcome.
Hope this helps.