[SalesForce] Controller property set to null after ActionFunction execution

I am having a weird behavior of actionfunction.
I have two of them.
The problem occurs when clicking on the commandButton. At the end, javascript function testc() is executed, which calls test2() (second actionfunction).
Before calling test2(), alert('{!signinred}') gives non null value of 'signinred' controller property which is set in 'signin' apex method. But after calling test2() which means executing 'aftersignin' apex method, I debug the value of signinred in that method, and it's null.

I have been stumbling over this for hours. Am I missing something?
I appreciate any help

<apex:actionFunction action="{!signin}" name="testa" reRender="none">                  
    <apex:param name="mail" value="" assignTo="{!email}" />                   
    <apex:param name="pass" value="" assignTo="{!passw}" />                   
</apex:actionFunction>
<apex:actionFunction action="{!aftersignin}" name="test2" reRender="">    
<apex:commandButton onclick="jsFunctionName1();" oncomplete="testc()" value="Sign In" styleClass="myButton" />

<script> 
   function jsFunctionName1(){                             
      var ema = document.getElementsByClassName("form-control")[0].value;                              
      var pass = document.getElementsByClassName("form-control1")[0].value;                             
      if(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(ema)){                                  
         testa(ema,pass);                                                              
      }                             
      else{alert("You have entered an invalid email address!");}                            
}
   function testc(){                                    
      alert("Email = " + '{!email}' + "; pass = " + '{! passw}');                                                                  
      var ema = document.getElementsByClassName("form-control")[0].value;                                   
      var pass = document.getElementsByClassName("form-control1")[0].value;                                   
      if(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(ema)){
          var numb = '{!numuse}';                  
          alert(numb);                     
          var passw = '{!pass_acc}';                            
          if (numb != '0'){                                  
             if (pass != passw){                                  
                 alert("You entered the wrond password");                              
             }
             else{test2();}                            
          }
       else{alert('{!signinred}');test2();}                                
    }                             
}

In Controller:

public pagereference aftersignin(){
     System.debug(LoggingLevel.Error, signinred );
     if (signinred) {return page.viewbooking;}
     else {return page.page1;}
}

Best Answer

If you put some apex variable in the javascript code, the variable will retain its value. So if you for example define signinred = false; in the constructor and then put this variable on the page into the javascript code it will initialize only once while the page is loaded and will remain false till some visualforce element rerenders this area.

If you want to change a value of apex variable on the visualforce page with javascript for later use in controller you should use one of the following visualforce elements:

  • apex:param with one of the following components:
    • apex:actionFunction
    • apex:commandButton
    • apex:inputHidden
    • apex:actionSupport
    • apex:commandLink
    • apex:outputLink
  • JavaScript Remoting
  • AJAX Toolkit

In your case I would use apex:param together with the actionFunction to pass a value to the variable. Then create some output visualforce element (outputPanel for example), put variable there and then rerender this panel to see the current value of the variable:

<apex:actionFunction action="{!aftersignin}" name="test2" reRender="output">
    <apex:param name="p1" value="" assignTo="{!signinred}" />
</apex:actionFunction>

<script> 
function testc(){                                    
    if(wrongPassword){
        test2(false);
    }
    else{
        test2(true);
    }                                
}  
</script> 

<apex:outputPanel id="output" layout="none">
    signinred: {!signinred}
</apex:outputPanel>

And don't forget, that if no reRender attribute is defined for the apex:commandButton then after click on it the page will reload. As a result all variable values are lost. To prevent the page reload you should use rerender attribute or use return false; in the onClick after the function call:

<apex:commandButton onclick="jsFunctionName1(); return false;"
                    oncomplete="testc()" 
                    value="Sign In" 
                    styleClass="myButton" />
Related Topic