4

I have a pageblocktable with one editable column in which numeric value for quantity will be entered. the next column to this is the Rate column which will have values from Salesforce. I want the Product of these 2 to be displayed in the last column as Total and also the sum of the Total column in Javascript so that on entering values in the inputtext, the total dynamically changes.

Below is my page :

<apex:page controller="DetailController" sidebar="false" id="pg">
<script>
function findTotal(){
alert(document.getElementById('pg:frmId:pb:pbt:0:qty').value);
//    alert(document.getElementById('pg:frmId:pb:pbt:0:j_id38').txt);
var qty = document.getElementById('pg:frmId:pb:pbt:0:qty').value;
var rate = document.getElementById('pg:frmId:pb:pbt:0:j_id38').text; 
var totallineItem = qty*rate;
//    document.getElementById('pg:frmId:pb:pbt:0:qty').value
document.getElementById("pg:frmId:pb:pbt:0:j_id26").innerHTML = totallineItem ; 
}



</script>
<apex:form id="frmId">


<apex:pageBlock title="Order Line Items" rendered="{!showDetails}" id="pb">
<apex:pageblockButtons location="bottom">
<apex:commandButton action="{!createOrder}" value="Save"/>
</apex:pageblockButtons>
<apex:pageBlockTable value="{!DispWrapper}" var="dw" id="pbt">
<apex:column value="{!dw.lineItemObj.Product__c}"/>
<apex:column value="{!dw.lineItemObj.Order__c }"/>
<apex:column headerValue="Delivered Quantity" >
<apex:inputtext value="{!dw.quantity}" id="qty" onchange="findTotal();"   styleClass="count-me"/>
 </apex:column>
 <apex:column value="{!dw.lineItemObj.Rate__c }" id="rate"/>
 <apex:column headerValue="Total">
 <apex:outputtext id="litotal"></apex:outputtext>
 </apex:column>
 </apex:pageBlockTable>
 </apex:pageBlock>

 </apex:form>
 </apex:page>

I am not familiar with Javascript and so this code is all I have which I tried. Please point me in the right direction to proceed with this!

The sample image below shows a typical table. The last column and the summary (Totals) need to be populated via Javascript. Sample Table

6

The DOM Id values in Visualforce tables include a row number (the :0: in your JavaScript) so your logic needs to incorporate that. The approach that I think works best is to use a CSS class (that has no markup associated with it) instead of the DOM Id:

<apex:column headerValue="Delivered Quantity" >
    <apex:inputtext value="{!dw.quantity}" styleClass="quantityMarker"/>
</apex:column>
<apex:column value="{!dw.lineItemObj.Rate__c }" styleClass="rateMarker"/>
<apex:column headerValue="Total">
    <apex:outputtext styleClass="totalMarker"/>
    <apex:facet name="footer">
        <apex:outputtext styleClass="grandTotalMarker"/>
    </apex:facet>
</apex:column>

While you could achieve what you want with just JavaScript, I would recommend adding (as a static resource) and using jQuery in your page. The code then becomes something like this (that you should add to the end of the page so the page rendering is not held up):

<script src="{!$Resource.jQuery}"></script>
<script>
(function($) {
    $(document).ready(function() {
        $('.quantityMarker').change(function() {

            var defaultedFloat = function(s) {
                if (s !== null && s !== '') {
                    var r = parseFloat(s);
                    if (!isNaN(r)) return r;
                }
                return 0;
            };

            // Recalculate the row
            var q = $(this);
            var r = q.closest('tr').find('.rateMarker');
            var t = q.closest('tr').find('.totalMarker');
            // Better handling of rounding may be needed
            t.text(defaultedFloat(q.val()) * defaultedFloat(r.text()));

            // Recalculate total of all rows
            var total = 0;
            $('.totalMarker').each(function() {
                var t = $(this);
                total += defaultedFloat(t.text());
            });
            $('.grandTotalMarker').text(total);
        });
    });
})(jQuery.noConflict());
</script>

This code:

  • Executes jQuery.noConflict() so any existing value of $ in the page is preserved
  • Waits until the DOM is ready
  • Then adds a function that is notified of changes on all elements that have class .quantityMarker
  • When a change happens, the function finds the class rateMarker element in the same row and the totalMarker element in the same row
  • Then sets the product in the totalMarker element = Then sums all the row totals into the grand total
  • Thanks for the quick reply Keith. I have included jQuery file in my static resource and then tried your code. is there something else that needs to be done to populate the Totals column as its still not getting populated - do i need to include javascript code like document.getElementById('total').value= value obtained from jQuery? – Sid Aug 1 '16 at 10:14
  • I've typed this code in without trying it myself so there are probably mistakes in it but I think its pretty much complete. The first thing to do is look at your browser's console for errors and you can add console.log calls to the above code as the most simple debugging technique. But if you are going to write JavaScript you need to learn about debugging techniques for it e.g. How do I start to debug my own Visualforce/JavaScript? as most of us makes mistakes when writing it. – Keith C Aug 1 '16 at 10:20
  • I just pasted the original code into jshint.com and fixed two problems in the code - I've updated the code in the answer. Doesn't guarantee the code will work, but at least makes sure its syntactically correct. – Keith C Aug 1 '16 at 10:27
  • Thanks for the suggestion Keith. I was able to do a bit of debugging and the code is working fine now as I am getting the desired result in the Totals column. However, can you please also guide me to get the value of Total of the Totals column below the table (could be part of table itself or separately). I believe the grandtotalmarker is supposed to calculate that, but how do i display the same on my page? (really sorry for asking very basic questions!!!!) – Sid Aug 1 '16 at 10:33
  • I've added to the Visualforce making use of the apex:facet name="footer" to add a grandTotalMarker cell at the bottom of the total column. – Keith C Aug 1 '16 at 10:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.