0

In visualforce page, I have a javascript for loop which calls a action function according to elements size

VF Page :

<apex:form>
    <apex:actionFunction name="myActionFunction" action="{!actionFunctionMethod}" rerender="source,srcTable" oncomplete="">
    </apex:actionFunction>
</apex:form>
<script>
    function addToList {
        for (var i = 0; 1 < ele.length; i++) {
            myActionFunction(); // This calls a method in contoller
        }
    }
</script>

In Controller, I have a list initialized by its constructor and I add values by actionFunction as:

public with sharing class Details {
    List < WrapperClass > detailsList {get;set;}
    public Details() {
        detailsList = new List < WrapperClass > ();
    }
    public void actionFunctionMethod() {
        detailsList.add(new WrapperClass());
        System.debug('======  ' + detailsList.size()); // In system debug it is always 1
    }
    public class WrapperClass {
        public WrapperClass() {}
    }
}

Lets suppose the for loop execute myActionFunction 5 times. So, method actionFunctionMethod called 5 times and List must have size of 5. But it is always 1.

The Expected value for List should be 5 but actual value is 1. Context is same, page didn't reload but how this happening? and what should be work around it controller don't maintain values like this way?

I think some how list get initialized otherwise it will through null pointer exception. I have checked my code there is no initialization except constructor.

1 Answer 1

1

The problem is that the view state isn't updated before the next call, so each of the X functions are submitted with the same view state, and the net result is that you'll end up with X copies of the same view state at the end (X-1 of which are discarded, leaving you in the same state at the end).

You should either pass a parameter to the function to add the number of rows you want, or chain the calls together one after the other. For chaining, it might look like this:

var queue = [], inQueue = false
function addNext() {
    inQueue = queue.length
    if(queue.length) {
        myActionFunction()
    }
}
function addAll() {
    [].forEach.call(ele, function(v) { queue.push(v) })
    if(!inQueue) addNext()
}

Then, in your actionFunction:

<apex:actionFunction name="myActionFunction" action="{!actionFunctionMethod}" 
    onComplete="addNext()" reRender="form" />
2
  • Thanks for your response.. I got the problem it.. rather than calling onComplete every time.. I can prepare all data in for loop for assigning to Map or JSON data for ActionFunction. Could you know how to assign to JS Map or JSON. & pass that data to action params and in Controller how we deseralize the data..
    – user6836
    Jun 23, 2016 at 18:54
  • @user6836 Just add an apex:param to your apex:actionFunction and pass the value to your function when you call it. Use the assignTo attribute of the param to bind it to a variable in your controller. It can be pretty much any primitive data type, and it will be deserialized automatically.
    – sfdcfox
    Jun 23, 2016 at 19:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .