+ Start a Discussion
Collen Mayer 6Collen Mayer 6 

Visualforce- Adding Row / List Size not corresponding

I've got a visualforce page with javascript formulas totaling records at the bottom.  I've recently added the ability to add a row to the page by clicking a button.  However the size of my list (!PayrollDistributionList.size) is not increasing when I do that (unless I "save" and refresh the page), so my column total ends up incorrect, and it doesn't iterate over all the rows.   Can someone provide some guidance?

My page:
<apex:page standardController="Payroll_Authorization__c" sidebar="false" doctype="html-5.0" standardStylesheets="false" extensions="PayrollAuthorization_extn" applyBodyTag="true" lightningStylesheets="true">
<head>
  <meta charset="utf-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"/>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  <style>
      .form-control {
          padding: 6px !important;
      }
      .btn-info {
        color: #fff!important;
        background-color: #5bc0de !important;
        border-color: #46b8da !important;
        background-image: none !important;
        padding: 8px 20px !important;
    }
     .table>thead>tr>th{
            vertical-align: top !important;
            text-align: left !important;
      }
      .table>tbody>tr>td{
            vertical-align: top !important;
            text-align: left !important;
      }
      .table>tbody>tr>td, .table>tbody>tr>th, .table>tfoot>tr>td, .table>tfoot>tr>th, .table>thead>tr>td, .table>thead>tr>th {
            padding: 4px !important;
        }
        .list-group-item {
            padding: 6px 15px !important;
        }
  </style>
	<script>
	      
    function calctotal(){
          alert ("caltotal" + {!PayrollDistributionList.size}); 
          var tempRowTotal=0;
          var percenttotal= 0;
        for(var i=1; i<={!PayrollDistributionList.size};i++ ){
              
              tempRowTotal = ($('.wh'+i).val()!= null && $('.wh'+i).val() != '')?parseFloat($('.wh'+i).val()):0.0;
              percenttotal  += tempRowTotal;
              
          	}
        return percenttotal;   
    }
      
    function calcRow(){
          alert ("calrow"); 
          
        var tempRowTotal=0;
         var percenttotal= 0;
           percenttotal= calctotal(); 
 		for(var i=1; i<={!PayrollDistributionList.size};i++ ){	
          tempRowTotal = ($('.wh'+i).val()!= null && $('.wh'+i).val() != '')?parseFloat($('.wh'+i).val()):0.0;
          $('.wp' + i).text(((tempRowTotal * 100)/percenttotal).toFixed(2)+'%');
          $('.percenttotal').text(percenttotal.toFixed(2)+'%');		
          }
      }
    
    $(document).ready(function(){
              {
                  calcRow();
         	  }

      });
    </script>
    </head>
<body>
	<apex:form >
        <apex:pageBlock title="Payroll Distribution" id="er" >
		<div align="center" draggable="false" style="font-size:13px; margin-bottom:4px"  >
    		<apex:commandButton value="Save" action="{!SavePA}" styleclass="btn btn-info" style="" />&nbsp;&nbsp;
    		<apex:commandButton value="Cancel" action="{!Cancel}" styleclass="btn btn-info" immediate="true"/>
		</div>
		<div class="container-flud" style="font-size: 11.5px;">
    		<apex:pageMessages ></apex:pageMessages>
    		<div class="col-md-12" style="margin-bottom: -15px;">
        		<ul class="list-group">      
            		<li class="list-group-item row" style="background-color: #702342;color: #fff;padding: 6px 10px;">
                		<h4 style="margin: 2px 0px;font-size: 12px;font-weight: bolder;">Payroll Authorization</h4>
            		</li>
        		</ul>

      <div class="col-md-12" style="margin-bottom: 15px;">
        <ul class="list-group">      
            <li class="list-group-item row" style="background-color: #702342;color: #fff;padding: 6px 10px;">
                <h4 style="margin: 2px 0px;font-size: 12px;font-weight: bolder;">Payroll Distributions</h4>
            </li>
        </ul>
    	</div>
	<table class="table table-bordered" >
                   
                <thead>
                <tr>
                <th>
                    Program
                </th>
                <th>
                    Percentage worked
                </th>
                <th>
                	Percentage total
                </th>
              </tr>
                </thead>
                <tbody>
                    <apex:variable value="{!1}" var="index"/>  
                <apex:repeat value="{!PayrollDistributionList}" var="pd">
                    <tr>
                        <td><apex:inputfield value="{!pd.Program__c}"   style="Width: 50%"/></td>
                        <td ><apex:inputfield value="{!pd.Program_Percent__c}" styleClass="wh{!index}" onkeyup="calcRow()"/> </td>
                    	<td Class="wp{!index}">
                    		0%
                		</td>
                    </tr>
                    <apex:variable value="{!index+1}" var="index"/>
                   
                </apex:repeat>
    		</tbody>
        <tfoot> <tr>
                <th>
                </th>
                <th class="percenttotal">
                    0.0%
                </th>
                <th>
                	100.00%
                </th>
              </tr></tfoot>
          </table>
          </div>
   		</div>
    <apex:commandButton action="{!addRow}" value="Add Program" immediate="true" reRender="er"/>
        </apex:pageBlock>
        </apex:form>
    
    </body>
</apex:page>
My extension: 
 
public with sharing class PayrollAuthorization_extn {
   
    public list <PA_Distribution__c> PayrollDistributionList {get; set;}
    public Payroll_Authorization__c PA;
    
    
    public PayrollAuthorization_extn(ApexPages.StandardController controller) {
        
  	PA = (Payroll_Authorization__c)controller.getRecord();
  	PayrollDistributionList = [Select Id, Name, Program__r.Name, Program_Percent__c
 			From PA_Distribution__c
      		Where Payroll_Authorization__r.id =: controller.getId()];  
                
    }
    
    public void addRow(){
 		PayrollDistributionList.add(new PA_Distribution__c(	Payroll_Authorization__c = PA.id));
	}
    
    public void SavePA (){
        upsert PA; 
        upsert PayrollDistributionList;
    }
    
    
}


 
Best Answer chosen by Collen Mayer 6
NagendraNagendra (Salesforce Developers) 
Hi Mayer,


You are using the list from controller directly in JavaScript, on load it has correct value as its being rendered/loaded.

When you add call controller property to add a row, value in JavaScript is not refreshed automatically.

You have couple of options:
  1. Easiest is to rerender script on calling command button:
    <apex:outputPanel id="scriptPanel"/>
        <script>
            // your code, here you would get refreshed value
        </script>
    </apex:outputPanel>
    
    <!-- add rerender to script panel -->
    <apex:commandButton action="{!addRow}" value="Add Program" 
        immediate="true" reRender="er, scriptPanel"/>
    Note: Here make sure to remove document.ready() outside the script panel which is reloaded every time, otherwise it would fire as well.
  2. Use a apex:inputHidden and oncomplete event on apex:commandButton:
    <script>
        function calcRow() {
            // access listsize as
            $( "input[name$='listsize']" ).val()
        }
    </script>
    <apex:pageBlock title="Payroll Distribution" id="er" >
        <!-- hidden input would be refreshed -->
        <apex:inputHidden value="{!PayrollDistributionList.size}" id="listsize"/>
        <!-- adding oncomplete -->
        <apex:commandButton action="{!addRow}" value="Add Program" 
            immediate="true" reRender="er" oncomplete="calcRow()"/>
    </apex:pageBlock>

    Hope this helps you.
Kindly mark this as solved if it;s resolved so that it gets removed from the unanswered queue which results in helping others who are encountering a similar issue.

Thanks,
Nagendra

All Answers

NagendraNagendra (Salesforce Developers) 
Hi Mayer,


You are using the list from controller directly in JavaScript, on load it has correct value as its being rendered/loaded.

When you add call controller property to add a row, value in JavaScript is not refreshed automatically.

You have couple of options:
  1. Easiest is to rerender script on calling command button:
    <apex:outputPanel id="scriptPanel"/>
        <script>
            // your code, here you would get refreshed value
        </script>
    </apex:outputPanel>
    
    <!-- add rerender to script panel -->
    <apex:commandButton action="{!addRow}" value="Add Program" 
        immediate="true" reRender="er, scriptPanel"/>
    Note: Here make sure to remove document.ready() outside the script panel which is reloaded every time, otherwise it would fire as well.
  2. Use a apex:inputHidden and oncomplete event on apex:commandButton:
    <script>
        function calcRow() {
            // access listsize as
            $( "input[name$='listsize']" ).val()
        }
    </script>
    <apex:pageBlock title="Payroll Distribution" id="er" >
        <!-- hidden input would be refreshed -->
        <apex:inputHidden value="{!PayrollDistributionList.size}" id="listsize"/>
        <!-- adding oncomplete -->
        <apex:commandButton action="{!addRow}" value="Add Program" 
            immediate="true" reRender="er" oncomplete="calcRow()"/>
    </apex:pageBlock>

    Hope this helps you.
Kindly mark this as solved if it;s resolved so that it gets removed from the unanswered queue which results in helping others who are encountering a similar issue.

Thanks,
Nagendra
This was selected as the best answer
Collen Mayer 6Collen Mayer 6
Perfect.  Thanks so much.