[SalesForce] Visualforce – Apex Parameters are not getting passed to controller

VF Code

<apex:pageBlock title="New Expense" rendered="{!isNewExpense}" id="pb">
<apex:pageBlockButtons >
<apex:commandButton value="Save New Expense" action="{!save}" rerender="pb" >
<apex:param name="Exp_Date" value="{!Expense__c.Date__c}" assignTo="{!Exp_Date}"/>
<apex:param name="Exp_Type" value="{!Expense__c.Type__c}" assignTo="{!Exp_Type}"/>
<apex:param name="Exp_Amount" value="{!Expense__c.Amount__c}" assignTo="{!Exp_Amount}"/>
<apex:param name="Exp_Comments" value="{!Expense__c.Comments__c}" assignTo="{!Exp_Comments}"/>
</apex:commandButton>
<apex:commandButton action="{!cancel}" value="Cancel"/>
</apex:pageBlockButtons>

Controller code

public with sharing class ExpenseController
{

private ApexPages.StandardSetController sc;
private ApexPages.StandardController sc1;
public Integer SumOfAllExpenses {get; set;}
public Boolean isTwenty {get; set;}
public String pwd{get;set;}
public Boolean isNewExpense {get;set;}

public Date Exp_Date{get;set;}
public String Exp_Type{get;set;}
public Integer Exp_Amount{get;set;}
public String Exp_Comments{get;set;}


public ExpenseController(ApexPages.StandardSetController sc)
{
this.sc = sc;
SumOfAllExpenses = displayTotal();
isTwenty = getTwenty();
 
}


public Integer displayTotal()
{

List<AggregateResult> i = [SELECT SUM(Amount__c) FROM Expense__c];
SumOfAllExpenses = Integer.valueOf(i[0].get('expr0'));
return SumOfAllExpenses;
}

public void Custom_Delete()
{
System.debug('Checking for Pwd..');
List<Expense__c> l = [SELECT Id FROM Expense__c WHERE IsDeletedFromUI__c = true];
System.debug('Records to be deleted :'+l);
if(l.size() > 0)
{
if(pwd == 'KVN')
{
System.debug('Custom_Delete Invoked');

delete l;

System.debug('Custom_Delete Completed');
}
if(pwd != 'KVN' || pwd=='')
{
for(Expense__c ll : [SELECT Id FROM Expense__c WHERE IsDeletedFromUI__c = true])
{
ll.isDeletedFromUI__c = false;
update ll;
}


ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.ERROR,'Incorrect Password.Delete Cannot Be Processed');
ApexPages.addMessage(myMsg);
}
}
}

public Boolean getTwenty()
{

Integer cnt = [SELECT COUNT() FROM Expense__c];
System.debug('Cnt variable is :'+cnt);
//Integer Cnt = Integer.valueOf(j[0].get('expr0'));
if(cnt > 20) 
{
return true;
}
else
{
return false;
}
}


public PageReference save()
{
System.debug('Before Save - Comments Value :'+(Expense__c)sc.getRecord());
cancelNew();
System.debug('OUTSIDE INSERT'+Exp_Date+' '+Exp_Amount);   //*****LINE 0******

if(Exp_Date != null && Exp_Amount != null)
{
System.debug('WITHIN INSERT');
Expense__c e1 = new Expense__c();
e1.Date__c = Exp_Date;
e1.Amount__c = Exp_Amount;
e1.Type__c = Exp_Type;
e1.Comments__c = Exp_Comments;
insert e1;
}
sc.save();
Custom_Delete();
System.debug('After Save - Comments Value :'+(Expense__c)sc.getRecord());
displayTotal();
System.debug('After Total - Comments Value :'+(Expense__c)sc.getRecord());
PageReference p = new PageReference('/apex/addExpenses');
return p;

}

public PageReference cancel()
{
cancelNew();
sc.cancel();
displayTotal();
PageReference p = new PageReference('/apex/addExpenses');
return p;

}

public void needNew()
{
isNewExpense = true;
}

public void cancelNew()
{
isNewExpense = false;
}



}


}

My understanding so far :

a) User presses "Save" upon which save() in the controller extension class will be called.

b) I am also sending <apex:param>s to the corresponding properties in the controller.

c) I expect that at LINE 0, apex parameters from VF page (Exp_Date and Exp_Amount) will be sent but I am getting only null values as shown by the debug log.

06:36:07.106 (106966000)|USER_DEBUG|[85]|DEBUG|OUTSIDE INSERTnull 0

Can anyone let me know as to why my apex parameters are not sent to the controller properties ?

UPDATE :

Looks like there is an issue with

<apex:param name="Exp_Date" value="{!Expense__c.Date__c}" assignTo="{!Exp_Date}"/>
<apex:param name="Exp_Type" value="{!Expense__c.Type__c}" assignTo="{!Exp_Type}"/>
<apex:param name="Exp_Amount" value="{!Expense__c.Amount__c}" assignTo="{!Exp_Amount}"/>
<apex:param name="Exp_Comments" value="{!Expense__c.Comments__c}" assignTo="{!Exp_Comments}"/>

Because when I hard code values like "xyz" instead of "{!Expense__c.Comments__c}" in the apex:param tag I can obtain "xyz" from the controller (as revealed from the log).

Is there anything wrong in the apex:param tag especially with "value" attribute assignment ?
Can someone let me know ?

Best Answer

Apex:param tags can be tricky.They generally work great when you use rerender else sometime they fail. And most important they are able to pass string values to the the controller.

Can you try to convert the value of params to text before passing it ?

Something like

<apex:param name="Exp_Date" value="{!TEXT(Expense__c.Date__c)}" assignTo="{!Exp_Date}"/>

OR

<apex:param name="Exp_Date" value="{!JSINHTMLENCODE(Expense__c.Date__c)}" assignTo="{!Exp_Date}"/>

You can try with JSENCODE, I think for me the TEXT() function worked.