java.lang.Object
ortus.boxlang.runtime.components.Component
ortus.boxlang.runtime.components.system.Loop

@BoxComponent(description="Create loops for iterating over collections and ranges", requiresBody=true) public class Loop extends Component
The Loop component provides various iteration mechanisms for BoxLang applications. This component is the BoxLang equivalent of ColdFusion's cfloop tag and supports multiple loop types including query loops, array loops, list loops, collection loops, conditional loops, numeric range loops, file iteration, and grouped query loops.
See Also:
  • Constructor Details

    • Loop

      public Loop()
      Constructs a new Loop component with all supported attributes configured.

      The Loop component supports multiple, mutually exclusive loop types. Different combinations of attributes determine which loop type is executed:

      • Query Loop: Requires query attribute
      • Grouped Query Loop: Requires query and group attributes
      • Array Loop: Requires array attribute
      • List Loop: Requires list attribute
      • Collection Loop: Requires collection and item attributes
      • Numeric Range Loop: Requires index, from, and to attributes
      • Conditional Loop: Requires condition attribute
      • Times Loop: Requires times attribute
      • File Loop: Requires file and index attributes
  • Method Details

    • _invoke

      public Component.BodyResult _invoke(IBoxContext context, IStruct attributes, Component.ComponentBody body, IStruct executionState)
      Executes the appropriate loop type based on the provided attributes.

      This method serves as the main entry point for all loop operations, analyzing the provided attributes to determine which specific loop type to execute and delegating to the appropriate helper method.

      Supported Loop Types

      • Query Loop: Iterate over query recordsets with optional row range constraints
      • Grouped Query Loop: Process query data with grouping on specified columns
      • Array Loop: Iterate over array elements with optional index tracking
      • List Loop: Process delimited lists with customizable delimiters
      • Collection Loop: Iterate over Java collections and structures
      • Numeric Range Loop: Loop through numeric ranges with configurable step values
      • Conditional Loop: Continue looping while a condition remains true
      • Times Loop: Execute a specific number of iterations
      • File Loop: Read text files line by line

      Loop Control

      All loop types support standard loop control statements:

      • break - Exit the loop immediately
      • continue - Skip to the next iteration
      • return - Exit from the containing function/component

      Loop control statements can be labeled to target specific nested loops:

       <bx:loop label="outer" array="#outerArray#" item="outerItem">
         <bx:loop array="#innerArray#" item="innerItem">
           <bx:if condition="#someCondition#">
             <bx:break label="outer" /> // Breaks out of outer loop
           </bx:if>
         </bx:loop>
       </bx:loop>
       

      Usage Examples

      Query Loop

       // Simple query loop
       <bx:loop query="#myQuery#">
         <bx:output>#myQuery.name#: #myQuery.email#</bx:output>
       </bx:loop>
      
       // Query loop with row range
       <bx:loop query="#myQuery#" startRow="5" endRow="15">
         <bx:output>Row #currentRow#: #myQuery.name#</bx:output>
       </bx:loop>
       

      Grouped Query Loop

       // Group by department
       <bx:loop query="#employeeQuery#" group="department">
         <h3>Department: #department#</h3>
         <bx:loop> // Inner loop for employees in this department
           <p>#name# - #position#</p>
         </bx:loop>
       </bx:loop>
      
       // Nested grouping (department > manager > employee)
       <bx:loop query="#employeeQuery#" group="department">
         <h2>Department: #department#</h2>
         <bx:loop group="manager">
           <h3>Manager: #manager#</h3>
           <bx:loop> // Individual employees
             <p>#name# - #position#</p>
           </bx:loop>
         </bx:loop>
       </bx:loop>
       

      Array Loop

       // Loop with item only
       <bx:loop array="#myArray#" item="currentItem">
         <bx:output>#currentItem#</bx:output>
       </bx:loop>
      
       // Loop with both item and index
       <bx:loop array="#myArray#" item="currentItem" index="currentIndex">
         <bx:output>Item #currentIndex#: #currentItem#</bx:output>
       </bx:loop>
       

      List Loop

       // Default comma delimiter
       <bx:loop list="apple,banana,cherry" item="fruit">
         <bx:output>#fruit#</bx:output>
       </bx:loop>
      
       // Custom delimiter
       <bx:loop list="apple|banana|cherry" item="fruit" delimiters="|">
         <bx:output>#fruit#</bx:output>
       </bx:loop>
       

      Numeric Range Loop

       // Basic range
       <bx:loop from="1" to="10" index="i">
         <bx:output>#i#</bx:output>
       </bx:loop>
      
       // With step
       <bx:loop from="0" to="100" step="10" index="i">
         <bx:output>#i#</bx:output> // Outputs: 0, 10, 20, 30...
       </bx:loop>
      
       // Backward iteration
       <bx:loop from="10" to="1" step="-1" index="i">
         <bx:output>#i#</bx:output> // Outputs: 10, 9, 8, 7...
       </bx:loop>
       

      Collection Loop

       // Structure iteration
       <bx:loop collection="#myStruct#" item="key">
         <bx:output>#key#: #myStruct[key]#</bx:output>
       </bx:loop>
       

      Conditional Loop

       <bx:loop condition="#hasMoreData()#">
         <bx:set processNextBatch() />
       </bx:loop>
       

      Times Loop

       <bx:loop times="5" index="i">
         <bx:output>Iteration #i#</bx:output>
       </bx:loop>
       

      File Loop

       <bx:loop file="/path/to/file.txt" index="line">
         <bx:output>#line#</bx:output>
       </bx:loop>
       
      Specified by:
      _invoke in class Component
      Parameters:
      context - The context in which the Component is being invoked
      attributes - The attributes to the Component
      body - The body of the Component
      executionState - The execution state of the Component
      Returns:
      A BodyResult indicating how the loop terminated (normal completion, break, continue, or return)
      Throws:
      BoxRuntimeException - if required attributes are missing or invalid for the detected loop type