This approach is officially unsupported

Somewhere around APIv30 (ish?) visualforce dropped support for this. From the docs:

Note: does not support reassignment inside of an iteration component, such as <apex:dataTable> or <apex:repeat>. The result of doing so, e.g., incrementing the <apex:variable> as a counter, is unsupported and undefined.

The original post for the sake of posterity. It should work on older API versioned pages, but I certainly don't encourage it.


I was recently developing a rather simple visualforce page designed to create a master object, and a list of new child objects in a single page wizard, and all was going well: field sets were deployed, the "add row' button was ready to let you add more child objects to the list, but then came the last step: the remove row button.

I pulled up a public domain trashcan icon and was all set to use it as the body of an apex:commandLink to remove the row when the realization hit: these rows haven't been saved to the database yet; they don't have any field I can use as a unqiue ID!

After some thinking, and a little bit of swearing, I had an idea! Use the apex:variable tag to define a variable and increment it inside the apex:pageBlockTable iteration component to give the row number. This quickly failed, every row ended up with an index of 0, and it turns out this is use of redefining apex:variables inside of an iteration component is officially unsupported.

While I had the visualforce reference open though I did notice something that gave me one last idea based off an undocumented feature of visualforce dynamic bindings that lets you access arrays by index in the form of {!array[0]} or {!array[index]}. With a little bit of apex like so, and using "array" as my list of child objects:

public List<Integer> getArrayIndexes(){  
List<Integer> indexes = new List<Integer>();  
for(integer i = 0; i &lt;= (array.size()-1); i++){  
    indexes.add(i);
}
return indexes;  

Now we can use this trick and new method on our visualforce page like so:

And with that, our wizard now lets us remove items at will, even if they don't have an ID field set on them yet!


That took way more work that it should, but it's a great example of just how awesome dynamic visualforce bindings are. Kudos to the visualforce team for a quite well done feature.

Well, that or you could just use javascript, but where's the fun in that?