--- title: "How to: Build a Simple Looping Data Workflow" slug: "how-to-build-a-simple-looping-data-workflow" description: "Learn to create a looping Data Workflow to efficiently send personalized emails to multiple clients, enhancing your data processing skills." updated: 2026-02-02T20:30:19Z published: 2026-02-03T15:48:58Z canonical: "docs.unqork.io/how-to-build-a-simple-looping-data-workflow" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.unqork.io/llms.txt > Use this file to discover all available pages before exploring further. # How to: Build a Simple Looping Data Workflow **UDesigner** Iterators, like the [Data Workflow](/v1/docs/data-workflow-component) component, often handle only one element of an array at a time. But what if you need to repeat the process to iterate on more elements? In this how-to guide, you’ll learn about a **looping Data Workflow** to achieve this task. is and how to build one. ## What Is a Looping Data Workflow? Looping Data Workflows let you perform operations on consecutive rows of an array. Imagine you have a list of clients you need to email a renewal notice to. You might have that list in a table like the following: | clientName | clientEmail | product | renewalPrice | | --- | --- | --- | --- | | Chelsea | chelsea@therainbowcompany.com | Many Hue | $1,999 | | Noor | noor@thebuildingcompany.com | Construct It | $3,500 | | Jadzia | jadzia@thebigcompany.com | Oversize | $70,000 | | Alejandro | alejandro@thestartup.com | Grow Up | $1,000 | To send out these emails manually, you’d use the following process: 1. Look at the list of clients, and see who needs to be emailed. 2. Retrieve the necessary details from the first row. 3. Complete and send the email to the first client. 4. Return to the list and see if others need to be emailed. 5. Repeat Steps 2 through 4 until each client on the list has been emailed. But you don't want to send a generic email to every person on your list. Instead, you want to send a personalized email that follows this template: `To: {{clientEmail}}` `Hello {{clientName}},` `This is a notification that your product license for {{product}} will renew next year for {{renewalPrice}}. Please contact your account manager if you have any questions.` `Best,` `Our Company Services   ` To see how this process works with a looping Data Workflow, look at the following diagram. ![](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/Dwf_SimpleLoop_Diagram.png?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A19Z&se=2026-11-09T04%3A51%3A19Z&sr=c&sp=r&sig=PD8WEyh9BrvySbS6XCA8bfJQobPWps6MDdvOhru5MyA%3D) Here, **Step 1** is some form of an input. In our example, this would be a table storing your client data. **Step** **2** is some form of logic to determine which row is next. In our case, it looks for which index in your table is next. Data from the next index is sent into the operation, which is represented by **Step 3**. In our case, this operation is sending an email to your client. At **Step** **2**, if there are no additional indexes to process, the loop finishes. Then, it concludes at **Step** **4**. ## Configuration This configuration can seem complex, but keep in mind the five steps you'd take to send these emails manually. > [!NOTE] > These instructions assume you have a new module open, saved, and with a title. ### Configure the Data Table Component Begin by configuring a [Data Table](/v1/docs/data-table-component) component to store your client list and their information. 1. In the Module Builder, drag and drop a **Data Table** component onto your canvas. 2. In the **Property ID** and **Label Text** fields, enter `dtClients`. 3. In the data table, enter the following: | # | clientName | clientEmail | product | renewalPrice | | --- | --- | --- | --- | --- | | 1 | Chelsea | chelsea@therainbowcompany.com | Many Hue | $1,999 | | 2 | Noor | noor@thebuildingcompany.com | Construct It | $3,500 | | 3 | Jadzia | jadzia@thebigcompany.com | Oversize | $70,000 | | 4 | Alejandro | alejandro@thestartup.com | Grow Up | $1,000 | ![](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/image(871).png?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A19Z&se=2026-11-09T04%3A51%3A19Z&sr=c&sp=r&sig=PD8WEyh9BrvySbS6XCA8bfJQobPWps6MDdvOhru5MyA%3D) 4. Click **Save Component**. ### Configure the First Hidden Component Each row in your table has a number assigned to it. That number is called the index. Use a [Hidden](/v1/docs/hidden-component) component to add a place for your application to keep track of which row it last processed. Indexes start at `0`, indicating the first row. So, set the **Default Value** to `0`. Later, you’ll add logic that increases this number, one value at a time. 1. Drag and drop a **Hidden** component onto your canvas, placing it below your Data Table component. 2. In the **Property ID** and **Label Text** fields, enter `index`. 3. In the **Default Value** field, enter `0`. 4. Click **Save Component**. ### Configure the First Data Workflow Component Next, configure a [Data Workflow](/v1/docs/data-workflow-component) component to create your looping logic. 1. Drag and drop a **Data Workflow** component onto your canvas, placing it below your Hidden component. 2. In the **Property ID** and **Canvas Label Text** fields, enter `dwfLoop`. #### Configure the First Input Operator This [Input](/v1/docs/input-operator) operator references your `index` **Hidden** component, which determines the row in your data table that needs processing next. 1. Drag and drop an **Input** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Input | | Component | index | | Required | Yes | | Source | Default | #### Configure the First Formula Operator This [Formula](/v1/docs/formula-operator) operator takes the previous index that was processed (`A`) and adds `1` to it. > [!NOTE] > The `A` value acts as an alias for values passed to the operator. 1. Drag and drop a **Formula** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Formula Value | | Label | Index + 1 | | Formula/Expression | =SUM(A,1) | 3. Connect the output port (right) of the **Input** operator to the input port (left) of the **Formula** operator. #### Configure the First Output Operator This [Output](/v1/docs/output-operator) operator outputs the data from the Formula operator to the `index` **Hidden** component. The formula updates the Hidden component’s **Default Value** by adding **1** to it. Now, with each loop of the Data Workflow, the value passed to the `index` **Input** operator increases by `1`. 1. Drag and drop an **Output** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Output | | Component | index | | Action | value | 3. Connect the output port (right) of the **Formula** operator to the input port (left) of the **Output** operator. #### Configure the Second Input Operator This [Input](/v1/docs/input-operator) operator brings your actual client data into your Data Workflow. 1. Drag and drop another **Input** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Input | | Component | dtClients | | Required | Yes | | Source | Default | #### Configure the Size Operator For your Data Workflow to understand when all the data has been processed, you’ll use a [Size](/v1/docs/size-operator) operator to count the number of objects in the array. Meaning the number of clients in your table. 1. Drag and drop a **Size** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Size | | Label | How many clients are there? | 3. Connect the output port (right) of the `dtClients` **Input** operator to the input port (left) of the **Size** operator. #### Configure the Second Formula Operator This [Formula](/v1/docs/formula-operator) operator creates an expression that determines if your `index` **Hidden** component is less than the value returned by your Size operator. You’ll use the following expression: `=CONCATENATE(A,"<",_arg)`, where `A` is the value from your `index` **Hidden** component and `_arg` is the value located by your Size operator. Later, you’ll use a [Decision](/v1/docs/decision-operator) operator to determine whether this statement is **true**. 1. Drag and drop another **Formula** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Formula Value | | Label | More clients? | | Formula/Expression | =CONCATENATE(A,"<",_arg) | 3. Connect the output port (right) of the `index` **Input** operator to the input port (left) of the `More clients?` **Formula** operator. 4. Connect the output port (right) of the **Size** operator to the argument port (top) of the `More clients?` **Formula** operator. #### Configure the First Console Operator You’ll add several [Console](/v1/docs/console-operator) operators during this configuration to view the data in the DevTools Console in Express View. This Console operator lets you view the result of your `More clients?` **Formula** operator. 1. Drag and drop a **Console** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Console | | Label | Condition | 3. Connect the output port (right) of the `More clients?` **Formula** operator to the input port (left) of the **Console** operator. #### Configure the Decision Operator This [Decision](/v1/docs/decision-operator) operator determines whether there are more emails to send by looking at the expression created by your `More clients?` **Formula** operator. If this expression is **true**, the Decision operator passes your data through its upper output port. If this expression is **false**, the Decision operator passes your data through its lower output port. So, your `dtClients` **Input** operator serves as the input and your `More clients?` **Formula** operator serves as the argument. Your Data Workflow should continue to loop until there are no more rows to input from your Data Table component. So, you're using `A<_arg` to determine if the number stored in the `index` **Hidden** component is less than the total number of rows in the table. After the first loop of the Data Workflow, the value stored in the `index` **Hidden** component is `1`. In the next loop, the Data Workflow processes the second row of the table (**index 1**). After your Data Workflow processes the fourth and final row of the table, the value stored in the `index` **Hidden** component is `4`. This is no longer less than four, so in the next loop, the Decision operator evaluates the `A<_arg` statement as `false` to stop the loop. 1. Drag and drop a **Decision** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Decision | | Input List | | | Condition | _arg | 3. Connect the output port (right) of the `dtClients` **Input** operator to the input port (left) of the **Decision** operator. 4. Connect the output port (right) of the `More clients?` **Formula** operator to the argument port (top) of the **Decision** operator. #### Configure the Second Console Operator This [Console](/v1/docs/console-operator) operator lets you view the data your Decision operator passes to its upper input port. 1. Drag and drop another **Console** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Console | | Label | True | 3. Connect the upper output port (right) of the **Decision** operator to the input port (left) of the `True` **Console** operator. #### Configure the Third Console Operator This [Console](/v1/docs/console-operator) operator lets you view the data your Decision operator passes to its lower input port. 1. Drag and drop another **Console** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Console | | Label | False | 3. Connect the lower output port (right) of the **Decision** operator to the input port (left) of the `False` **Console** operator. #### Configure the Get Operator Once you've determined if there are more emails to send, the next step is to retrieve the data needed to send the next email. Here, you’ll connect a [Get](/v1/docs/get-operator) operator to your Decision operator so your `dtClients` **Data Table** component data passes through. Then, set your `index` **Input** operator as the argument to remind the Get operator which row of your table is next. 1. Drag and drop a **Get** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Get | | Label | Get Current Row | | Path | [_arg] | 3. Connect the upper output port (right) of the **Decision** operator to the input port (left) of the **Get** operator. 4. Connect the output port (right) of the `Index` **Input** operator to the argument port (top) of the **Get** operator. #### Configure the Fourth Console Operator This [Console](/v1/docs/console-operator) operator lets you view the data retrieved by the Get operator. 1. Drag and drop another **Console** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Console | | Label | Current Row | 3. Connect the output port (right) of the **Get** operator to the input port (left) of the `Current Row` **Console** operator. ![](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/image(882).png?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A19Z&se=2026-11-09T04%3A51%3A19Z&sr=c&sp=r&sig=PD8WEyh9BrvySbS6XCA8bfJQobPWps6MDdvOhru5MyA%3D) 4. Click **Save Component**. ### Configure the Second Hidden Component Before configuring the rest of your Data Workflow, add a place to store the results. This [Hidden](/v1/docs/hidden-component) component stores each row of data retrieved by your [Get](/v1/docs/get-operator) operator. Your loop overwrites this each time it runs. So, this component only stores the row you're currently emailing. 1. Drag and drop a **Hidden** component onto your canvas, placing it below your Data Workflow component. 2. In the **Property ID** and **Label Text** fields, enter `currentRow`. 3. Click **Save Component**. ### Update the First Data Workflow Component Now that you have a [Hidden](/v1/docs/hidden-component) component to store the results, you’ll update your Data Workflow component to output the data to this Hidden component. Then, you’ll reference this data in a separate Data Workflow later. The second Data Workflow sends your emails, while the first manages your loop. 1. Hover over the `dwfLoop` **Data Workflow** component. A toolbar displays above the component on hover-over. 2. Using the toolbar, click the ![](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/Screenshot 2025-09-15 202009(1).png?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A19Z&se=2026-11-09T04%3A51%3A19Z&sr=c&sp=r&sig=PD8WEyh9BrvySbS6XCA8bfJQobPWps6MDdvOhru5MyA%3D) (**Settings**) button. #### Configure the Second Output Operator This [Output](/v1/docs/output-operator) operator sends the data to your `currentRow` **Hidden** component. 1. Drag and drop another **Output** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Output | | Component | currentRow | | Action | value | 3. Connect the output port (right) of the **Get** operator to the input port (left) of the `currentRow` **Output** operator. 4. Click **Save Component**. ### Configure the Second Data Workflow Component Now that you have your loop configured, set up another [Data Workflow](/v1/docs/data-workflow-component) component to send your emails. 1. Drag and drop another **Data Workflow** component onto your canvas, placing it below your `currentRow` **Hidden** component. 2. In the **Property ID** and **Canvas Label Text** fields, enter `dwfOperation`. #### Configure the Input Operator This [Input](/v1/docs/input-operator) operator brings in the data stored in your `currentRow` **Hidden** component. When sending your emails, you’ll reference this component instead of the larger data table because it stores the data for a single client at a time. 1. Drag and drop an **Input** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Input | | Component | currentRow | | Required | Yes | | Source | Default | #### Configure the Console Operator This [Console](/v1/docs/console-operator) operator lets you view the data retrieved from the `currentRow` **Hidden** component. 1. Drag and drop a **Console** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Console | | Label | Email Sent | 3. Connect the output port (right) of the **Input** operator to the input port (left) of the **Console** operator. #### Configure the Output Operator Next, add an [Output](/v1/docs/output-operator) operator to trigger your first Data Workflow to run again once an email is sent. 1. Drag and drop an **Output** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Output | | Component | dwfLoop | | Action | trigger | 3. Connect the output port (right) of the **Input** operator to the input port (left) of the **Output** operator. ![](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/image(883).png?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A19Z&se=2026-11-09T04%3A51%3A19Z&sr=c&sp=r&sig=PD8WEyh9BrvySbS6XCA8bfJQobPWps6MDdvOhru5MyA%3D) 4. Click **Save Component**. ### Update the First Data Workflow Component Now that you have a Data Workflow configured to run your operation, configure your first Data Workflow to trigger it. Doing so stops the loop once everyone is sent an email. 1. Hover over the `dwfLoop` **Data Workflow**. A toolbar displays above the component on hover-over. 2. Using the toolbar, click the ![](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/Screenshot 2025-09-15 202009(1).png?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A19Z&se=2026-11-09T04%3A51%3A19Z&sr=c&sp=r&sig=PD8WEyh9BrvySbS6XCA8bfJQobPWps6MDdvOhru5MyA%3D) (**Settings**) button. #### Configure the Third Output Operator Configure another [Output](/v1/docs/output-operator) operator to trigger the second Data Workflow to run. 1. Drag and drop another **Output** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Output | | Component | dwfOperation | | Action | trigger | 3. Connect the output port (right) of the **Get** operator to the input port (left) of the `dwfOperation` **Output** operator. #### Configure the Fourth Output Operator Remember, your [Decision](/v1/docs/decision-operator) operator determines whether there are more emails to send. If there aren't, the Decision operator passes data to its lower output port. So, you’ll add an [Output](/v1/docs/output-operator) operator to stop the looping process. 1. Drag and drop another **Output** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Output | | Component | _self | | Action | value | 3. Connect the lower output port (right) of the **Decision** operator to the input port (left) of the `_self` **Output** operator. 4. Click **Save Component**. ### Configure the Initializer Component Lastly, add an [Initializer](/v1/docs/initializer-component) component to begin the entire process. 1. Drag and drop an **Initializer** component onto your canvas, placing it above your Data Table component. 2. In the **Property ID** and **Canvas Label Text** fields, enter `initLoop`. 3. From the **Trigger Type** drop-down, select `New Submission`. 4. In the **Outputs** table, enter the following: | # | Source | Type | Value | | --- | --- | --- | --- | | 1 | dwfLoop | trigger | GO | ![](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/image(884).png?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A19Z&se=2026-11-09T04%3A51%3A19Z&sr=c&sp=r&sig=PD8WEyh9BrvySbS6XCA8bfJQobPWps6MDdvOhru5MyA%3D) 5. Click **Save Component**. 6. **Save** your module. Here's how your module looks in the Module Builder: ![](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/image(885).png?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A19Z&se=2026-11-09T04%3A51%3A19Z&sr=c&sp=r&sig=PD8WEyh9BrvySbS6XCA8bfJQobPWps6MDdvOhru5MyA%3D) Preview your module in Express View and open the DevTools Console. Activity from your various Console operators populates, showing the loop is working correctly. The first section of the image displays the path your first row of data takes through your Data Workflows. Your `Condition` **Console** operator displays the expression of `0<4` because it’s the `0` index in your data, and there are `4` items in your table. The `True` **Console** operator displays your original data, and the `False` **Console** operator displays `_BLOCKED` because the expression `0<4` is **true**. From there, your first row of data is separated. You can see this in your `Current Row` **Console** operator. Then, you also see that data in your `Email Sent` **Console** operator, indicating the data has passed through your second Data Workflow. The Console operators below this data display the rest of your data through the same process. You can expand this data in your DevTools Console to see more details. The second portion of this image displays where your loop ends. Here, you see `4<4` in the `Condition` **Console** operator, showing that your Data Workflow has processed your data with an index of `4`. Because `4<4` is a **false** statement, your data takes that path instead. The `True` **Console** operator displays `_BLOCKED`, and now your data displays under the `False` **Console** operator. Once your loop reaches this point, the process stops. ![](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/Dwf_SimpleLoop_Console_01.jpg?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A19Z&se=2026-11-09T04%3A51%3A19Z&sr=c&sp=r&sig=PD8WEyh9BrvySbS6XCA8bfJQobPWps6MDdvOhru5MyA%3D) **Classic Designer** Iterators, like the [Data Workflow](/v1/docs/data-workflow-component) component, often handle only one element of an array at a time. But what if you need to repeat the process to iterate on more elements? In this how-to guide, you’ll learn about a **looping Data Workflow** to achieve this task. is and how to build one. ## What Is a Looping Data Workflow? Looping Data Workflows let you perform operations on consecutive rows of an array. Imagine you have a list of clients you need to email a renewal notice to. You might have that list in a table like the following: | clientName | clientEmail | product | renewalPrice | | --- | --- | --- | --- | | Chelsea | chelsea@therainbowcompany.com | Many Hue | $1,999 | | Noor | noor@thebuildingcompany.com | Construct It | $3,500 | | Jadzia | jadzia@thebigcompany.com | Oversize | $70,000 | | Alejandro | alejandro@thestartup.com | Grow Up | $1,000 | To send out these emails manually, you’d use the following process: 1. Look at the list of clients, and see who needs to be emailed. 2. Retrieve the necessary details from the first row. 3. Complete and send the email to the first client. 4. Return to the list and see if others need to be emailed. 5. Repeat Steps 2 through 4 until each client on the list has been emailed. But you don't want to send a generic email to every person on your list. Instead, you want to send a personalized email that follows this template: `To: {{clientEmail}}` `Hello {{clientName}},` `This is a notification that your product license for {{product}} will renew next year for {{renewalPrice}}. Please contact your account manager if you have any questions.` `Best,` `Our Company Services   ` To see how this process works with a looping Data Workflow, look at the following diagram. ![](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/Dwf_SimpleLoop_Diagram.png?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A19Z&se=2026-11-09T04%3A51%3A19Z&sr=c&sp=r&sig=PD8WEyh9BrvySbS6XCA8bfJQobPWps6MDdvOhru5MyA%3D) Here, **Step 1** is some form of an input. In our example, this would be a table storing your client data. **Step** **2** is some form of logic to determine which row is next. In our case, it looks for which index in your table is next. Data from the next index is sent into the operation, which is represented by **Step 3**. In our case, this operation is sending an email to your client. At **Step** **2**, if there are no additional indexes to process, the loop finishes. Then, it concludes at **Step** **4**. ## Configuration This configuration can seem complex, but keep in mind the five steps you'd take to send these emails manually. > [!NOTE] > These instructions assume you have a new module open, saved, and with a title. ### Configure the Data Table Component Begin by configuring a [Data Table](/v1/docs/data-table-component) component to store your client list and their information. 1. In the Module Builder, drag and drop a **Data Table** component onto your canvas. 2. In the **Property ID** and **Canvas Label Text** fields, enter `dtClients`. 3. In the data table, enter the following: | # | clientName | clientEmail | product | renewalPrice | | --- | --- | --- | --- | --- | | 1 | Chelsea | chelsea@therainbowcompany.com | Many Hue | $1,999 | | 2 | Noor | noor@thebuildingcompany.com | Construct It | $3,500 | | 3 | Jadzia | jadzia@thebigcompany.com | Oversize | $70,000 | | 4 | Alejandro | alejandro@thestartup.com | Grow Up | $1,000 | ![](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/image(886).png?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A19Z&se=2026-11-09T04%3A51%3A19Z&sr=c&sp=r&sig=PD8WEyh9BrvySbS6XCA8bfJQobPWps6MDdvOhru5MyA%3D) 4. Click **Save & Close**. ### Configure the First Hidden Component Each row in your table has a number assigned to it. That number is called the index. Use a [Hidden](/v1/docs/hidden-component) component to add a place for your application to keep track of which row it last processed. Indexes start at `0`, indicating the first row. So, set the **Default Value** to `0`. Later, you’ll add logic that increases this number, one value at a time. 1. Drag and drop a **Hidden** component onto your canvas, placing it below your Data Table component. 2. In the **Property ID** and **Canvas Label Text** fields, enter `index`. 3. In the **Default Value** field, enter `0`. 4. Click **Save & Close**. ### Configure the First Data Workflow Component Next, configure a [Data Workflow](/v1/docs/data-workflow-component) component to create your looping logic. 1. Drag and drop a **Data Workflow** component onto your canvas, placing it below your Hidden component. 2. In the **Canvas Label Text** and **Property Name** fields, enter `dwfLoop`. #### Configure the First Input Operator This [Input](/v1/docs/input-operator) operator references your `index` **Hidden** component, which determines the row in your data table that needs processing next. 1. Drag and drop an **Input** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Input | | Component | index | | Required | Yes | | Source | Default | #### Configure the First Formula Operator This [Formula](/v1/docs/formula-operator) operator takes the previous index that was processed (`A`) and adds `1` to it. > [!NOTE] > The `A` value acts as an alias for values passed to the operator. 1. Drag and drop a **Formula** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Formula Value | | Label | Index + 1 | | Formula/Expression | =SUM(A,1) | 3. Connect the output port (right) of the **Input** operator to the input port (left) of the **Formula** operator. #### Configure the First Output Operator This [Output](/v1/docs/output-operator) operator outputs the data from the Formula operator to the `index` **Hidden** component. The formula updates the Hidden component’s **Default Value** by adding **1** to it. Now, with each loop of the Data Workflow, the value passed to the `index` **Input** operator increases by `1`. 1. Drag and drop an **Output** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Output | | Component | index | | Action | value | 3. Connect the output port (right) of the **Formula** operator to the input port (left) of the **Output** operator. #### Configure the Second Input Operator This [Input](/v1/docs/input-operator) operator brings your actual client data into your Data Workflow. 1. Drag and drop another **Input** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Input | | Component | dtClients | | Required | Yes | | Source | Default | #### Configure the Size Operator For your Data Workflow to understand when all the data has been processed, you’ll use a [Size](/v1/docs/size-operator) operator to count the number of objects in the array. Meaning the number of clients in your table. 1. Drag and drop a **Size** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Size | | Label | How many clients are there? | 3. Connect the output port (right) of the `dtClients` **Input** operator to the input port (left) of the **Size** operator. #### Configure the Second Formula Operator This [Formula](/v1/docs/formula-operator) operator creates an expression that determines if your `index` **Hidden** component is less than the value returned by your Size operator. You’ll use the following expression: `=CONCATENATE(A,"<",_arg)`, where `A` is the value from your `index` **Hidden** component and `_arg` is the value located by your Size operator. Later, you’ll use a [Decision](/v1/docs/decision-operator) operator to determine whether this statement is **true**. 1. Drag and drop another **Formula** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Formula Value | | Label | More clients? | | Formula/Expression | =CONCATENATE(A,"<",_arg) | 3. Connect the output port (right) of the `index` **Input** operator to the input port (left) of the **Formula** operator. 4. Connect the output port (right) of the **Size** operator to the argument port (top) of the **Formula** operator. #### Configure the First Console Operator You’ll add several [Console](/v1/docs/console-operator) operators during this configuration to view the data in the DevTools Console in Express View. This Console operator lets you view the result of your `More clients?` **Formula** operator. 1. Drag and drop a **Console** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Console | | Label | Condition | 3. Connect the output port (right) of the `More clients?` **Formula** operator to the input port (left) of the **Console** operator. #### Configure the Decision Operator This [Decision](/v1/docs/decision-operator) operator determines whether there are more emails to send by looking at the expression created by your `More clients?` **Formula** operator. If this expression is **true**, the Decision operator passes your data through its upper output port. If this expression is **false**, the Decision operator passes your data through its lower output port. So, your `dtClients` **Input** operator serves as the input and your `More clients?` **Formula** operator serves as the argument. Your Data Workflow should continue to loop until there are no more rows to input from your Data Table component. So, you're using `A<_arg` to determine if the number stored in the `index` **Hidden** component is less than the total number of rows in the table. After the first loop of the Data Workflow, the value stored in the `index` **Hidden** component is `1`. In the next loop, the Data Workflow processes the second row of the table (**index 1**). After your Data Workflow processes the fourth and final row of the table, the value stored in the `index` **Hidden** component is `4`. This is no longer less than four, so in the next loop, the Decision operator evaluates the `A<_arg` statement as `false` to stop the loop. 1. Drag and drop a **Decision** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Decision | | Input List | | | Condition | _arg | 3. Connect the output port (right) of the `dtClients` **Input** operator to the input port (left) of the **Decision** operator. 4. Connect the output port (right) of the `More clients?` **Formula** operator to the argument port (top) of the **Decision** operator. #### Configure the Second Console Operator This [Console](/v1/docs/console-operator) operator lets you view the data your Decision operator passes to its upper input port. 1. Drag and drop another **Console** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Console | | Label | True | 3. Connect the upper output port (right) of the **Decision** operator to the input port (left) of the `True` **Console** operator. #### Configure the Third Console Operator This [Console](/v1/docs/console-operator) operator lets you view the data your Decision operator passes to its lower input port. 1. Drag and drop another **Console** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Console | | Label | False | 3. Connect the lower output port (right) of the **Decision** operator to the input port (left) of the `False` **Console** operator. #### Configure the Get Operator Once you've determined if there are more emails to send, the next step is to retrieve the data needed to send the next email. Here, you’ll connect a [Get](/v1/docs/get-operator) operator to your Decision operator so your `dtClients` **Data Table** component data passes through. Then, set your `index` **Input** operator as the argument to remind the Get operator which row of your table is next. 1. Drag and drop a **Get** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Get | | Label | Get Current Row | | Path | [_arg] | 3. Connect the upper output port (right) of the **Decision** operator to the input port (left) of the **Get** operator. 4. Connect the output port (right) of the `Index` **Input** operator to the argument port (top) of the **Get** operator. #### Configure the Fourth Console Operator This [Console](/v1/docs/console-operator) operator lets you view the data retrieved by the Get operator. 1. Drag and drop another **Console** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Console | | Label | Current Row | 3. Connect the output port (right) of the **Get** operator to the input port (left) of the `Current Row` **Console** operator. ![](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/image(887).png?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A19Z&se=2026-11-09T04%3A51%3A19Z&sr=c&sp=r&sig=PD8WEyh9BrvySbS6XCA8bfJQobPWps6MDdvOhru5MyA%3D) 4. Click **Save**. ### Configure the Second Hidden Component Before configuring the rest of your Data Workflow, add a place to store the results. This [Hidden](/v1/docs/hidden-component) component stores each row of data retrieved by your [Get](/v1/docs/get-operator) operator. Your loop overwrites this each time it runs. So, this component only stores the row you're currently emailing. 1. Drag and drop a **Hidden** component onto your canvas, placing it below your Data Workflow component. 2. In the **Property ID** and **Canvas Label Text** fields, enter `currentRow`. 3. Click **Save & Close**. ### Update the First Data Workflow Component Now that you have a [Hidden](/v1/docs/hidden-component) component to store the results, you’ll update your Data Workflow component to output the data to this Hidden component. Then, you’ll reference this data in a separate Data Workflow later. The second Data Workflow sends your emails, while the first manages your loop. 1. Hover over the `dwfLoop` **Data Workflow**. A toolbar displays above the component on hover-over. 2. Using the toolbar, click the ![](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/Screenshot 2025-09-15 202009(1).png?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A19Z&se=2026-11-09T04%3A51%3A19Z&sr=c&sp=r&sig=PD8WEyh9BrvySbS6XCA8bfJQobPWps6MDdvOhru5MyA%3D) (**Settings**) button. #### Configure the Second Output Operator This [Output](/v1/docs/output-operator) operator sends the data to your `currentRow` **Hidden** component. 1. Drag and drop another **Output** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Output | | Component | currentRow | | Action | value | 3. Connect the output port (right) of the **Get** operator to the input port (left) of the `currentRow` **Output** operator. 4. Click **Save**. ### Configure the Second Data Workflow Component Now that you have your loop configured, set up another [Data Workflow](/v1/docs/data-workflow-component) component to send your emails. 1. Drag and drop another **Data Workflow** component onto your canvas, placing it below your `currentRow` **Hidden** component. 2. In the **Canvas Label Text** and **Property Name** fields, enter `dwfOperation`. #### Configure the Input Operator This [Input](/v1/docs/input-operator) operator brings in the data stored in your `currentRow` **Hidden** component. When sending your emails, you’ll reference this component instead of the larger data table because it stores the data for a single client at a time. 1. Drag and drop an **Input** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Input | | Component | currentRow | | Required | Yes | | Source | Default | #### Configure the Console Operator This [Console](/v1/docs/console-operator) operator lets you view the data retrieved from the `currentRow` **Hidden** component. 1. Drag and drop a **Console** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Console | | Label | Email Sent | 3. Connect the output port (right) of the **Input** operator to the input port (left) of the **Console** operator. #### Configure the Output Operator Next, add an [Output](/v1/docs/output-operator) operator to trigger your first Data Workflow to run again once an email is sent. 1. Drag and drop an **Output** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Output | | Component | dwfLoop | | Action | trigger | 3. Connect the output port (right) of the **Input** operator to the input port (left) of the **Output** operator. ![](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/image(888).png?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A19Z&se=2026-11-09T04%3A51%3A19Z&sr=c&sp=r&sig=PD8WEyh9BrvySbS6XCA8bfJQobPWps6MDdvOhru5MyA%3D) 4. Click **Save**. ### Update the First Data Workflow Component Now that you have a Data Workflow configured to run your operation, configure your first Data Workflow to trigger it. Doing so stops the loop once everyone is sent an email. 1. Hover over the `dwfLoop` **Data Workflow**. A toolbar displays above the component on hover-over. 2. Using the toolbar, click the ![](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/Screenshot 2025-09-15 202009(1).png?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A19Z&se=2026-11-09T04%3A51%3A19Z&sr=c&sp=r&sig=PD8WEyh9BrvySbS6XCA8bfJQobPWps6MDdvOhru5MyA%3D) (**Settings**) button. #### Configure the Third Output Operator Configure another [Output](/v1/docs/output-operator) operator to trigger the second Data Workflow to run. 1. Drag and drop another **Output** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Output | | Component | dwfOperation | | Action | trigger | 3. Connect the output port (right) of the **Get** operator to the input port (left) of the `dwfOperation` **Output** operator. #### Configure the Fourth Output Operator Remember, your [Decision](/v1/docs/decision-operator) operator determines whether there are more emails to send. If there aren't, the Decision operator passes data to its lower output port. So, you’ll add an [Output](/v1/docs/output-operator) operator to stop the looping process. 1. Drag and drop another **Output** operator onto your Data Workflow canvas. 2. Configure the operator's **Info** window as follows: | Setting | Value | | --- | --- | | Category | Output | | Component | _self | | Action | value | 3. Connect the lower output port (right) of the **Decision** operator to the input port (left) of the `_self` **Output** operator. 4. Click **Save**. ### Configure the Initializer Component Lastly, add an [Initializer](/v1/docs/initializer-component) component to begin the entire process. 1. Drag and drop an **Initializer** component onto your canvas, placing it above your Data Table component. 2. In the **Property ID** and **Canvas Label Text** fields, enter `initLoop`. 3. From the **Trigger Type** drop-down, select `New Submission`. 4. In the **Outputs** table, enter the following: | # | Property ID | Type | Value | | --- | --- | --- | --- | | 1 | dwfLoop | trigger | GO | ![](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/image(889).png?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A19Z&se=2026-11-09T04%3A51%3A19Z&sr=c&sp=r&sig=PD8WEyh9BrvySbS6XCA8bfJQobPWps6MDdvOhru5MyA%3D) 5. Click **Save & Close**. 6. **Save** your module. Here's how your module looks in the Module Builder: ![](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/image(890).png?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A19Z&se=2026-11-09T04%3A51%3A19Z&sr=c&sp=r&sig=PD8WEyh9BrvySbS6XCA8bfJQobPWps6MDdvOhru5MyA%3D) Preview your module in Express View and open the DevTools Console. Activity from your various Console operators populates, showing the loop is working correctly. The first section of the image displays the path your first row of data takes through your Data Workflows. Your `Condition` **Console** operator displays the expression of `0<4` because it’s the `0` index in your data, and there are `4` items in your table. The `True` **Console** operator displays your original data, and the `False` **Console** operator displays `_BLOCKED` because the expression `0<4` is **true**. From there, your first row of data is separated. You can see this in your `Current Row` **Console** operator. Then, you also see that data in your `Email Sent` **Console** operator, indicating the data has passed through your second Data Workflow. The Console operators below this data display the rest of your data through the same process. You can expand this data in your DevTools Console to see more details. The second portion of this image displays where your loop ends. Here, you see `4<4` in the `Condition` **Console** operator, showing that your Data Workflow has processed your data with an index of `4`. Because `4<4` is a **false** statement, your data takes that path instead. The `True` **Console** operator displays `_BLOCKED`, and now your data displays under the `False` **Console** operator. Once your loop reaches this point, the process stops. ![](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/Dwf_SimpleLoop_Console_01.jpg?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A19Z&se=2026-11-09T04%3A51%3A19Z&sr=c&sp=r&sig=PD8WEyh9BrvySbS6XCA8bfJQobPWps6MDdvOhru5MyA%3D) An array is a type of object that stores one or more data types. Data types supported in arrays include numbers, strings, and objects. The location of an element in an array. An object is a type of data structure that represents a single, self-contained entity that acts as a container for the characteristics of that entity. The DevTools Console helps you securely store, build, test, and deploy your software. Express View is how your end-user views your application. Express View also lets you preview your applications to test your configuration and view the styling. This is also the view your end-users will see when interacting with your application. After configuring a module, click Preview in the Module Builder to interact with the module in Express View. Triggers activate another component when certain requirements are met. Trigger types include Concurrent, Post, and Error. Some components do not have the ability to trigger others.