Details

    • Type: Improvement Improvement
    • Status: Resolved
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 1.6
    • Component/s: Engine
    • Labels:
      None

      Description

      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 )
        Unknown macro: { 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.

        Issue Links

          Activity

          No work has yet been logged on this issue.

            People

            • Assignee:
              Unassigned
              Reporter:
              Adrian Tarau
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development