#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]

Reply via email to