Skip to main content

How to Pass JavaScript Variables to Apex in Visualforce Using apex:actionFunction

While Lightning Web Components (LWC) are the modern standard for Salesforce development, thousands of organizations still rely on Visualforce pages for complex, legacy internal tools. One of the most common challenges developers face when maintaining these pages is figuring out how to pass dynamic values from the client-side (JavaScript) directly to the server-side (Apex controller).

The cleanest and most reliable way to bridge this gap in Visualforce is by utilizing the <apex:actionFunction> component paired with <apex:param> tags.

In plain words: An <apex:actionFunction> component automatically generates a JavaScript function on your page. When you call this function in your script, it silently triggers an asynchronous AJAX request to your Apex controller, allowing you to pass front-end variables directly into your backend code without refreshing the page.

Key Points Summary

  • The <apex:actionFunction> component must always live inside an <apex:form> tag to work.
  • It creates a seamless bridge between front-end user actions (like clicking a button or changing an input) and backend Apex logic.
  • You pass variables using child <apex:param> tags.
  • You can catch these variables in Apex using the assignTo attribute or by reading the page parameters manually.

Step 1: Define the actionFunction in Visualforce

First, you need to declare the function in your Visualforce markup. You will give the function a name (which becomes the JavaScript function name) and tie it to an action (the Apex method it will run).

<apex:form>
    <!-- This exposes a JavaScript function named 'passDataToApex' -->
    <apex:actionFunction name="passDataToApex" action="{!processData}" reRender="outputArea">
        <apex:param name="parameterName1" value="" assignTo="{!firstParam}" />
        <apex:param name="parameterName2" value="" assignTo="{!secondParam}" />
    </apex:actionFunction>
</apex:form>

Step 2: Invoke the Function in JavaScript

Now that the function is defined, you can call it anywhere in your client-side JavaScript. This could be inside an onclick handler, an event listener, or a custom script block. Simply pass your variables as arguments in the exact order they appear in your markup.

Real-Life Example: Invoking the JS Function
Here, we are passing two string variables directly into the actionFunction we created above.
<script>
    function sendVariables() {
        // Grab values from the DOM or set them dynamically
        var val1 = "Hello";
        var val2 = "Salesforce";

        // Call the actionFunction and pass the variables
        passDataToApex(val1, val2);
    }
</script>

Step 3: Access Parameters in the Apex Controller

There are two primary ways to grab these passed variables inside your Apex controller. You can either read them manually from the page URL parameters, or use automatic property binding.

Method A: Automatic Property Binding (Recommended)

If you used the assignTo attribute on your <apex:param> tags, Salesforce will automatically bind the incoming data to your Apex properties. Just make sure your properties have { get; set; } declared.

public class ActionFunctionController {
    
    // Properties tied to the assignTo attribute
    public String firstParam { get; set; }
    public String secondParam { get; set; }

    public void processData() {
        // The properties are already populated by the time this method runs!
        System.debug('Param 1 Value: ' + firstParam);
        System.debug('Param 2 Value: ' + secondParam);
    }
}

Method B: Reading Page Parameters Manually

If you didn't use assignTo, you can extract the values manually using the ApexPages reference map, targeting the name attribute of your params.

public class ActionFunctionController {

    public void processData() {
        // Retrieve values sent from JavaScript manually
        String value1 = ApexPages.currentPage().getParameters().get('parameterName1');
        String value2 = ApexPages.currentPage().getParameters().get('parameterName2');

        System.debug('Param 1 Value: ' + value1);
        System.debug('Param 2 Value: ' + value2);
    }
}
Common Developer Pitfalls:
  • Missing the Form Tag: <apex:actionFunction> will fail completely (usually silently) if it is not nested inside an <apex:form> tag.
  • Parameter Order Mismatch: The order of arguments passed in your JavaScript function call must strictly match the top-to-bottom sequence of the <apex:param> tags in your Visualforce markup.
  • Null Values with assignTo: If you are using the assignTo method, the Apex properties must have a setter (set;). Otherwise, the variables will arrive as null.

Frequently Asked Questions

Q: Should I use this for new Salesforce development?

A: No. While Visualforce is still supported by Salesforce, it is a legacy framework. For new development, you should build Lightning Web Components (LWC). In LWC, you pass parameters from JavaScript to Apex by calling an imperative Apex method or using an @wire adapter.

Q: Why did my page refresh when the actionFunction fired?

A: By default, action components will submit the form and refresh the page. To prevent this and make it a seamless background AJAX call, always include the reRender attribute on your actionFunction. Even if you don't need to update the UI, use reRender="none" (assuming you have a dummy element with that ID).

Golden Rule: Always specify a reRender attribute on your actionFunction. It tells the server to only refresh specific DOM sections, keeping your user's experience fast and fluid.
360 Summary Card
  • Parent Component: <apex:actionFunction> (Must be inside <apex:form>)
  • Variable Container: <apex:param>
  • JS Invocation: myFunctionName(arg1, arg2)
  • Apex Retrieval: assignTo (Automatic) or ApexPages.currentPage().getParameters().get() (Manual)