It is a very common requirement to build table rows or subforms that repeat for each item in an array (a one-to-many relationship in your data collection). Examples are for instance a table with line items in an invoice or a price quotation, or a list of covers in an insurance policy.

Inserting a Loop

Inserting a loop is a three step process.

Select the Element to Repeat

First, select the element in the canvas that you wish to repeat. Typically, this is a table row or a subform. 

In many cases the row to be repeated is the second row of a table, while the first row is used as a header row. 

Bind The Element to a Field

Locate the Data Bind property in the Properties panel to the right of the editing canvas and click the three dots to bring up the field selection dialog. Select a repeating element in the data collection. 


Mark as Repeating

Tick the box that says Repeat element for each entry. Most probably iText DITO will already tick this box for you.

Note that the resulting bind expression looks like this: items[*]. You can manually insert this expression in the Data Bind parameter as well.

Binding Data within a Loop

Once the loop is in place, you can start inserting fields in it. For line items in an invoice for instance, you could be required to bind an item description, a quantity, a unit price and a line item total for instance.

In the above scenario, insert rich text elements in the cells of the repeating row and start adding simple data bindings to those rich text elements. The same process applies if you insert other bound elements, like images for instance.

Instead of selecting fields via the wizard, you can also type the names of fields into the Data Bind property of the rich text element. Note that data binds which you insert inside a loop are relative to the root of the loop, not to the root of the data collection. You can use $ or $parent in the path if you have to bind a field relative to the root or to a parent item of loop's root.

Loop Properties

Filtering

You can create tables with repeating rows for any subset of a data array. Imagine that you have a list of line items in an invoice data set, and in the envisioned PDF document you want to build different tables, for instance to distinguish between line items of different types. 

Use the filter property on your loop to set the filter. To set the filter condition, you can use the same wizard as for conditional insertion of content.

Note that you can also set the filter trough syntax. The syntax to define the filtered loop looks like this:

iteratingElement[[conditionExpression]]

in which iteratingElement is the root element of the array and conditionExpression defines the filter.

To set the filter, you can use the operators in the table below. String values can be contained within single or double quotes.

Operator Name

 Type

 Syntax

 Expression Example

 Is equal to

 Text/Number

 ==

 {{fieldname}}=="fieldvalue"

 Is not equal to

 Text/Number

 !=

 {{fieldname}}!="fieldvalue"

 Is empty (string length is zero)

 Text

 isEmpty()

 isEmpty({{fieldname}})

 Is blank (no characters or only blank characters)

 Text

 isBlank()

 isBlank({{fieldname}})

 Is not empty

 Text

 !isEmpty()

 !isEmpty({{fieldname}})

 Is not blank

 Text

 !isBlank()

 !isBlank({{fieldname}})

 Contains

 Text

 contains()

 contains({{fieldname}}, "fieldvalue")

 Does not contain

 Text

 !contains()

 !contains({{fieldname}}, "fieldvalue")

 Is greater than

 Number

 >

 {{fieldname}}>fieldvalue

 Is greater than or equal to

 Number

 >=

 {{fieldname}}>=fieldvalue

 Is less than

 Number

 <

 {{fieldname}<fieldvalue

 Is less than or equal to

 Number

 <=

 {{fieldname}<=fieldvalue

 And

 Logical

 &&

 contains({{fieldname}}, "fieldvalue1")&&!contains({{fieldname}},"fieldvalue2")

 Or

 Logical

 ||

{{fieldname}}=="fieldvalue1"||{{fieldname}}=="fieldvalue2"

The operators in the table can be combined with the calculation functions that iText DITO supports, such as sum(), product(), concat() and size(). In our example, the expression size({{items[[{{producttype}} == 'wind mill']]}}) would return the number of items in that subarray.

Limiting

You can also set a minimum or maximum number of repetitions for the loop. 

Example

Imagine you have created a loop on table row, bound to an array with 6 iterations:

  • if you set the minimum number of repetitions to 10, a table with 10 rows will be generated. The first 6 rows will be bound to data iterations. 4 empty rows will be added to the end.
  • if you set the maximum number of repetitions to 5, a table with 5 rows will be generated. The first 5 iterations will be bound to the table, the sixth iteration will not be added to the table.