Lowdefy
Concepts/Lists/

Lists

List category blocks render multiple content areas, based on data in the state object.

Since the content area might contain input blocks, the block has an array value in state, with it's block id as key. For each item in the array, an content area (or set of content areas is rendered). Multiple list blocks can be nested.

List indices and block ids

If a block is to be rendered in an list's content area, the block id should contain a list index placeholder (specified with the $ symbol) for each list it is a part of. These placeholders will be populated with the blocks list indices. The list indices are a array of integers, indicating at which position in the list the block is, for each level of list blocks (zero indexed). The block id should be in valid dot-notation once the placeholders have been substituted.

This can be made more clear with a example. Suppose we have a list block with id contacts. Inside this list we have a text input block for the contact name. We would like our state to look like:

contacts:
  - name: Name 1
  - name: Name 2

The id for the text input block should be contacts.$.name. Each text input block will be given an indexed id based on it's position in the contacts list (contacts.0.name, contacts.1.name, etc.).

Suppose we also want to add a emails array for each contact. To do this, we can add another list block in the contacts array, and add a text input inside the emails array. If we want the emails to be a array of strings, i.e. our state should look like:

contacts:
  - name: Name 1
    emails:
      - email1@example.com
      - email2@example.com
  - name: Name 2
    emails: []

our config should look like:

id: contacts
type: ControlledList
properties:
  # ...
blocks:
  - id: contacts.$.name
    type: TextInput
    properties:
      # ...
  - id: contacts.$.emails
    type: ControlledList
    properties:
      # ...
    blocks:
      - id: contacts.$.emails.$
        type: TextInput
        properties:
          # ...

Note that the id of the emails list block is contacts.$.emails and that it has one $ placeholder since it is inside the contacts list, and the id of the email text input is contacts.$.emails.$, which has two $ placeholders since it is in both the contacts and contacts.$.emails lists.

The ids of the contacts.$.emails.$ text input blocks will look like contacts.0.emails.3 or contacts.2.emails.1, and this will result in the state where the emails on a contact are an array of strings.

List indices in operators

List indices are also supported in "getter" operators like _state. If the operator is given a key that contains $ placeholders, and the operator is called from a block with list indices, the placeholders will be populated with the blocks list indices. These indices are populated on actions called by the block, and are even populated in connections and requests if the block that triggered the Request action has list indices. This can be used to get values from the state array the block is a part of, or even values from another array at the same index.

List block methods

List blocks can provide methods to change their values. These are

pushItem

Add an item at the end of the list.

unshiftItem

Add an item at the start of the list.

removeItem

Remove an item at the specified index.

moveItemDown

Move the item at the specified index one position to the start of the list. If the item is at the start if the list, the item remains at position 0.

moveItemUp

Move the item at the specified index one position to the end of the list. If the item is at the end if the list, the item remains at it's position.

Example

id: page
type: PageHeaderMenu
blocks:
  - id: add_item_at_start
    type: Button
    events:
      onClick:
        - id: add_item_at_start
          type: CallMethod
          params:
            blockId: list
            method: unshiftItem
  - id: add_item_at_end
    type: Button
    events:
      onClick:
        - id: add_item_at_end
          type: CallMethod
          params:
            blockId: list
            method: pushItem
  - id: list
    type: List
    blocks:
      - id: list.$.move_item_down
        type: Button
        events:
          onClick:
            - id: move_item_down
              type: CallMethod
              params:
                blockId: list
                method: moveItemDown
                args:
                  - _index: 0 # Get the first index in the indices array
      - id: list.$.move_item_up
        type: Button
        events:
          onClick:
            - id: move_item_up
              type: CallMethod
              params:
                blockId: list
                method: moveItemUp
                args:
                  - _index: 0
      - id: list.$.remove_item
        type: Button
        events:
          onClick:
            - id: remove_item
              type: CallMethod
              params:
                blockId: list
                method: removeItem
                args:
                  - _index: 0

Lists and state

List blocks create a content area for each item in state. If state is updated, the list block will also update, creating or destroying content areas as necessary. Thus list blocks can also be manipulated by setting state directly using the SetState operator.