#foreach & velocityCount
------------------------
Key: VELOCITY-600
URL: https://issues.apache.org/jira/browse/VELOCITY-600
Project: Velocity
Issue Type: Improvement
Components: Engine
Reporter: Adrian Tarau
Priority: Minor
Fix For: 1.5.1
velocityCount = Used in the #foreach() directive, defines the string to be used
as the context key for the loop count. A template would access the loop count
as $velocityCount.
Knowing current version of the loop counter is very useful, but something is
missing. Very often, when you generate some content base on a model(JavaScript
code based on some UI model) you have the need to know if this is the last time
when the #foreach block will be executed or not.
Example
You have a collection of objects Property(bean with key, value fields) and you
want to generate a JavaScript object with them. The result should be like this :
{id : 1 , name = "John", ...}
you can generate this with
{
#foreach($property in $properties)
$property.key : "$property.value" #if($velocityCount != $properties.size())
, #end
#end
}
You can store $properties.size() of course outside the loop.
The template will be less verbose if I will have something like that.
#if($velocityHasNext) , #end.
Instead of saving only the counter, a new variable called velocityHasNext
whould be populated with the result of iterator.hasNext(). This is a minor
modification of current #foreach directive
while (!maxNbrLoopsExceeded && i.hasNext())
{
// TODO: JDK 1.4+ -> valueOf()
context.localPut(counterName , new Integer(counter));
context.localPut(hasNextName , i.hasNext()); <--- here is the change
Object value = i.next();
context.localPut(elementKey, value);
/*
* If the value is null, use the special null holder context
*/
if( value == null )
{
if( nullHolderContext == null )
{
// lazy instantiation
nullHolderContext = new NullHolderContext(elementKey,
context);
}
node.jjtGetChild(3).render(nullHolderContext, writer);
}
else
{
node.jjtGetChild(3).render(context, writer);
}
counter++;
// Determine whether we're allowed to continue looping.
// ASSUMPTION: counterInitialValue is not negative!
maxNbrLoopsExceeded = (counter - counterInitialValue) >=
maxNbrLoops;
}
also init should contain
public void init(RuntimeServices rs, InternalContextAdapter context, Node node)
throws TemplateInitException
{
super.init(rs, context, node);
counterName = rsvc.getString(RuntimeConstants.COUNTER_NAME);
hasNextName = rsvc.getString(RuntimeConstants.HAS_NEXT_NAME);
counterInitialValue =
rsvc.getInt(RuntimeConstants.COUNTER_INITIAL_VALUE);
....
}
This should help creating clear templates(and avoid some mistakes, sometime -
like using the wrong collection to test :) ).
Thanks.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]