function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
hgolovhgolov 

VF page reloading after actionFunction call, even though the apex method 'returns' void

Hi All,

Firstly, thanks for taking the time to read my post.

I have a vg page that has an actionFunction that calls an apex method from my custom controller. After running, there are a few components that are supposed to reload. However, what's happening is as follows:

1. The page starts to reload.

2. The apex method is called.

3. The components are NOT rerendered.

Does anyone have any ideas as to why that would happen?

Here is the relevant code:

1. ActionFunction tag:

  <apex:actionFunction name="undoEdit" action="{!undoEdit}" rerender="taskInfoDisplay, descInfo,fundraisingInfo, sysInfo,editButtons">
  <apex:param name="fieldToRollBack" value="{!fieldToRollBack}"/>
  </apex:actionFunction>

 

 

2. VF code that calls it:

 

<apex:commandButton image="xxx" onclick="undoEdit('Priority')" rendered="{!editState['Priority']}"/>

 

 

3. Apex Method:

 

public void undoEdit(){
		fieldToRollBack = ApexPages.currentPage().getParameters().get('fieldToRollBack');
		System.debug('the field is:' +  fieldToRollBack );
		//first check if this was edited
		if(editState.get(fieldToRollBack)){
			System.debug('the field was changed');
			if(origTaskVals.containsKey(fieldToRollBack)){
				System.debug('this is a task field, rolling back. The current val: ' + myTask.get(fieldToRollBack) + '. The orig val: ' + origTaskVals.get(fieldToRollBack));
				myTask.put(fieldToRollBack,origTaskVals.get(fieldToRollBack));
				System.debug('after putting, the val is: ' + myTask.get(fieldToRollBack))	;
			}
			
			editState.put(fieldToRollBack, false);
			
		}
	
	}

 

Thanks in advance for your help!

 

Best Answer chosen by Admin (Salesforce Developers) 
hgolovhgolov

To all who find this post:

Apex Controller: Editing the variable that is set in the action function:

 

<apex:actionFunction name="undoEdit" action="{!undoEdit}" rerender="counterStatus,taskInfoDisplay, descInfo,fundraisingInfo, sysInfo">
  <apex:param name="fieldToRollBack"   value="{!fieldToRollBack}"/>
  </apex:actionFunction>

 

 

in this case fieldToRollBack causes issues with the method to be called in the first place.

 

VisualForce Code: Adding a return false after the js function call prevents the undesired page reload

 

onclick="undoEdit('Priority');return false;

 

I hope this helps someone - it took me weeks to figure out!

 

All Answers

Ritesh AswaneyRitesh Aswaney

Hey, I'm wondering if its to do with the way you are passing the param. Are you able to retrieve the param okay in your controller ?

 

I'd use it like this. In the controller just have a setter for fieldToRollback which this action function will invoke and set the value, you don't need the getParameter bit. Worth a try.

 

<apex:actionFunction name="undoEdit" action="{!undoEdit}" rerender="taskInfoDisplay, descInfo,fundraisingInfo, sysInfo,editButtons">
  <apex:param name="fieldToRollBack" assignTo="fieldToRollBack" value="" />
  </apex:actionFunction>
hgolovhgolov

Firstly, thank you for your reply.

I tried that but it didn't work - any other suggestions?

Thanks

Jeremy-KraybillJeremy-Kraybill

This:

 

fieldToRollBack = ApexPages.currentPage().getParameters().get('fieldToRollBack');

is not necessary and is probably assigning null to this value. Remove it, make sure you have

 

assignTo = "{!fieldToRollBack}"

 

in your param, and you should be fine. If not, just add more debug parameters to your method because it's getting called, it just isn't having the results you expect.

 

Jeremy Kraybill

hgolovhgolov

Thanks for your reply, Jeremy.

When I tried doing as you suggested, the method never was called in the first place.

Right now, using the system log to view the debug, I see that the variable fieldToRollBack is assigned the correct value, and the rest of the method is executed. The only thing that doesn't happen is the rerendering of the page block section.

Any suggestions?

Ritesh AswaneyRitesh Aswaney

You might wanna revisit your rendering condition

rendered="{!editState['Priority']}

 

editState is presumably a map? You're checking if a value is present for the key 'Priority' ?

 

Unless the value is boolean, it should prolly read 

rendered="{!editState['Priority'] <> null }

 

or something along those lines ?

hgolovhgolov

Hi,

Yes, it is a map and the values are boolean. I've output that condition to the screen on a different line to be sure that it is correct, and it outputs as expected.

Any other ideas?

hgolovhgolov

To all who find this post:

Apex Controller: Editing the variable that is set in the action function:

 

<apex:actionFunction name="undoEdit" action="{!undoEdit}" rerender="counterStatus,taskInfoDisplay, descInfo,fundraisingInfo, sysInfo">
  <apex:param name="fieldToRollBack"   value="{!fieldToRollBack}"/>
  </apex:actionFunction>

 

 

in this case fieldToRollBack causes issues with the method to be called in the first place.

 

VisualForce Code: Adding a return false after the js function call prevents the undesired page reload

 

onclick="undoEdit('Priority');return false;

 

I hope this helps someone - it took me weeks to figure out!

 

This was selected as the best answer
heuyeheuye

i think i met the same problem,but i didn't understand well about your solution,can you help?

i use actionfuction in my custom component,and then use the custom component in a page.

 

1.actionfucntion should rerender components inside the custom component,but all page is reload.

 

 

<apex:pageBlockid="resultTable">
    <apex:actionRegion >     
       <apex:actionFunction reRender="resultTable" name="testaction" action="{!goToCurPage}" status="mystatus"  />       
       <apex:actionStatus startText="processing..." id="mystatus"></apex:actionStatus>
    </apex:actionRegion>
...

     <apex:inputText value="{!curPage}" onkeyup="testaction();"/>
</apex:pageBlock>    

 

 

controll:

 

 

public ApexPages.StandardSetController compSetController {get; set;}
...
public void setCurPage(integer nPageNum){
    this.compSetController.setPageNumber(nPageNum);
}

public void goToCurPage(){
}

 

 

hgolovhgolov

1. Try adding an <apex:param name="fieldToRollBack"   value="{!fieldToRollBack}"/> where the name is what you reference in the controller via the ApexPages.currentPage().getParameters().get('fieldToRollBack'); and the value is bound to the actual property in the controller.

2. Add a return false after your call to testaction();, like so:

<apex:inputText value="{!curPage}" onkeyup="testaction();return false;"/>

 

I hope this helps you!

arizonaarizona

This problem occurred only in Firefox for me.  

 

The fix was just to do this.

From:

<apex:actionFunction .... />

To: <apex:actionFunction ></apex:actionFunction>

 

Obviously this closes the script tag correctly.

 

 

Jennifer Lin 1Jennifer Lin 1
Thanks hgolov! Huge help here.
Soumya BasilSoumya Basil
Thank you hgolov !! 
Nilang PandeyNilang Pandey
Thanks hgolov!
Ashwin KhedekarAshwin Khedekar
To overcome the issue of page refreshing, inspite of using reRender attribute with apex:actionFunction (due to which queried data disappears from the VF page after being shown for a fraction of a second) :-
Avoid using both reRender attribute in actionFunction tag and return false; in apex:inputText tag in the onKeyUp event of this apex:inputText text box. Using only return false; in the onKeyUp event of apex:inputText is enough. It ensures that after the data is entered in the textbox and the enter key is hit, the page refreshes but the queried data from the controller is displayed correctly on the VF page. The data does not disappear in a fraction of a second.

In the below example, any account ID can be entered in the text box and the Enter key can be hit or the "Search Account" button can be hit. Doing any of these will fetch the account data and display it in a table on the VF page.

The controller class :-
public class AccountSearchCtlr
{
    public String accountId {get;set;}
    public List<Account> accountList {get;set;}
    
    public AccountSearchCtlr() {
        accountList = new List<Account>();
    }

    public pageReference searchAccount() {
        
        if(accountId != null && accountId.length() > 0) {

            // Remove leading and trailing spaces
            String trimmedAccountId = accountId.trim();
            
            if(trimmedAccountId.length() > 0) {

                accountList = [Select Id, Name, AccountNumber, Site from Account
                                where id = :trimmedAccountId];
                
                if(accountList.size() == 0) {
                    
                    ApexPages.addMessage(new ApexPages.Message(Apexpages.Severity.ERROR, 'No account found with this ID'));
                    accountList = new List<Account>();
                    
                } else if(accountList.size() == 1) {
                    ApexPages.addMessage(new ApexPages.Message(Apexpages.Severity.INFO, 'One account found with this ID'));
                }           
                
            } else {
                ApexPages.addMessage(new ApexPages.Message(Apexpages.Severity.ERROR, 'Please enter account ID'));
                accountList = new List<Account>();
            }
        } else {
            ApexPages.addMessage(new ApexPages.Message(Apexpages.Severity.ERROR, 'Please enter account ID'));
            accountList = new List<Account>();
        }
        return null;
    }
}

The VF page :- vfAccountSearchCtlr
<!--
  Browse for this VF page by appending /apex/vfAccountSearchCtlr to the URL.
-->
<apex:page controller="AccountSearchCtlr">
  <apex:pageMessages id="pageMessagesTag"/>

  <apex:form id="mainForm">

    <!-- reRender attribute is not used with this actionFunction -->
    <apex:actionFunction name="searchAccountAF" action="{!searchAccount}"/>
    
    <apex:pageBlock title="Enter Data" id="pageBlock1">

      Enter Account ID: &nbsp;

      <!-- return false; is enough with below tag -->      
      <apex:inputText value="{!accountId}" id="accountId" onKeyUp="processKeyUp(event,this);return false;"/>
  
      &nbsp;
      <apex:commandButton value="Search Account" action="{!searchAccount}" reRender="pageMessagesTag,pageBlock2"/>
    
    </apex:pageBlock>

    <apex:pageBlock id="pageBlock2" title="Account Details">
    
      <apex:pageBlockTable value="{!accountList}" var="a" id="outputTable" rendered="{!IF(accountList.size>0,true,false)}">
        <apex:column value="{!a.Id}"/>
        <apex:column value="{!a.Name}"/>
        <apex:column value="{!a.AccountNumber}"/>
        <apex:column value="{!a.Site}"/>
      </apex:pageBlockTable>
      
    </apex:pageBlock>
  </apex:form>

  <script type="text/javascript">
      function processKeyUp()
      {
           //alert('processKeyUp function starts');
           //alert('event.keyCode is ' + event.keyCode);

           if(event.keyCode == 13) {
               
               //alert('Enter key pressed, so calling actionFunction');
               searchAccountAF();
               
           } else {
                //alert('Some other key pressed, so not calling actionFunction');
           }
      }
  </script>
</apex:page>
 
shubham lathoriyashubham lathoriya
Try using button tag,hope this will help