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
Ralph CallawayRalph Callaway 

Bug with apex:variable when used in apex:pageBlockTable or apex:dataTable

I've got some really nasty formulas I'm building out and had hoped to use apex:variable to make the code more readable.  Problem is it appears that apex:variable doesn't work with apex:pageBlockTable and apex:dataTable.  Specifically the variable takes on the value for last row in every row.  The same effect does not happen with apex:repeat and apex:dataList.

 

Is this a bug or am I doing something wrong here?  I can't find anything in the documentation, but did find this post which has yet to be answered.

 

To see what I mean here's some sample code that illustrates the issues.

 

 

public with sharing class VariableInRepeatTest {

	public List<Integer> intArray { get; set; }
	{ intArray = new Integer[] { 1, 2, 3 }; }
}

 

<apex:page controller="VariableInRepeatTest">
<apex:pageBlock >
	<apex:pageBlockSection title="Variable in Page Block Table">
		<apex:pageBlockTable value="{!intArray}" var="int">
			<apex:variable var="variable" value="{!int}"/>
			<apex:column headerValue="Value" value="{!int}"/>
			<apex:column headerValue="Variable" value="{!variable}"/>
		</apex:pageBlockTable>
	</apex:pageBlockSection>
	<apex:pageBlockSection title="Variable in Repeat">
		<apex:repeat value="{!intArray}" var="int">
			<apex:variable var="variable" value="{!int}"/>
			Value: {!int} | Variable: {!variable}
		</apex:repeat>
	</apex:pageBlockSection>
	<apex:pageBlockSection title="Variable in Data List">
		<apex:dataList value="{!intArray}" var="int">
			<apex:variable var="variable" value="{!int}"/>
			Value: {!int} | Variable: {!variable}
		</apex:dataList>
	</apex:pageBlockSection>
	<apex:pageBlockSection title="Variable in Data Table">
		<apex:dataTable value="{!intArray}" var="int">
			<apex:variable var="variable" value="{!int}"/>
			<apex:column headerValue="Value" value="{!int}"/>
			<apex:column headerValue="Variable" value="{!variable}"/>
		</apex:dataTable>
	</apex:pageBlockSection>
</apex:pageBlock>
</apex:page>

 

 

 

aballardaballard

Yes, that is a known issue.  apex:variable was really not intended for use in this way and does not reliably "step through" different values of an iteration. 

Ralph CallawayRalph Callaway

It seems to work fine with apex:repeat and apex:datatable, so at least in some cases it can reliably "step through" an iteration. 

 

It's a bummer it doesn't work since it's very helpful to make very complex formulas legible.

 

I just wish if SFDC doesn't want to support it they'd make it a compile time error rather than letting us stumble through finding these little easter eggs.

aballardaballard

Even with repeat/datatable, there are definitely situations where it will give the wrong result.  It is not updated to the correct value at each point in the page processing lifecycle, so whther it seems to work depends on what use you make of it. 

 

 

Ralph CallawayRalph Callaway

Thanks for the tip.  Good to know there are pitfalls with apex:repeat and apex:dataList as well.

 

I just wish this produced some kind of compile/runtime error if it's not supported.  Or at least have a note in the documentation for apex:variable.

aballardaballard

Yes it should give a compile time error message.  Unfortunately Salesforce can't just add it now since there are people getting away with it in some situations.  So it would have to depend on the API version of the page.   And it works ok if it doesn't depend on any iteration variable.  Or controller method that might be different on each iteration.  

 

By the time we figured out when we can give an error message and when we can't it might be easier to just make it work :-) 

 

 

Ralph CallawayRalph Callaway

Ahh, the burdens of a platform.  Thanks for talking it out.  I know things on your side are never straightforward.  

 

If I were on that side I'd just throw the error anytime apex:variable is inside a repeater, it sounds like all the cases where it works would be addressed by just moving the tag outside the repeater and only enforce it for API > 21.0.  But then again, things seem easy when I don't have to look at the whole picture ;)

Mitesh SuraMitesh Sura
Post a solution if anybody has one. 
Anurag BhardwaajAnurag Bhardwaaj
In this case we need to increment the <apex:variable> in <apex:column>. We use the below snippet to resolve this issue.
<apex:variable var="i" value="{!0}" />
<apex:dataTable ... >
    <apex:column>
         <apex:variable var="i" value="{!i+1}" />
     </apex:column>
  </apex:dataTable>