Skip to content

Looping a block ​

Start a loop ​

Select the block that should repeat. Usually that's a Group that already holds the layout of one item, such as a card with an image and two lines of text. Click Loop this block in the toolbar, or Alt+right-click the block (Option+right-click on a Mac). The Data Loop panel in the block settings has the same options.

Select loop source shows the lists you can loop over:

  • Repeaters
  • Field Tables
  • Lists, and fields with several choices (Multiselect, Checkboxes)
  • Galleries
  • Files
  • Select Post and Select User fields that allow several items
  • Post and User Relations that allow several items
  • Content sections
  • A Recurring Date's entries, upcoming dates or previous dates

Then choose how many items to show:

  • Items to show (0 = all)
  • Skip first (offset): leave out the first few items, for example because the first photo is already shown as a hero image.

The panel shows how many items it found.

Design one item ​

The first item is the one you edit; the others are previews that update as you work. Click a preview item to make it the one you're editing, which helps when items look different.

Inside the loop, bind blocks with the normal paths: loop over @post(team), and a paragraph bound to @post(team.name) shows each member's name. There's no special "current item" syntax.

Show previewed items and Hide previewed items toggle the preview copies, which is useful when a long list makes the canvas hard to work with.

Loops inside loops ​

Loops can be nested. Loop over @post(team), then inside each card loop over @post(team.links): each member's links appear under that member, and @post(team.name) still refers to the member.

Don't nest two loops over the same list. The inner loop takes over, and the outer item can no longer be reached.

Numbering and separators ​

  • loop_index() gives the item's position, for a numbered list.

  • is_first() and is_last() check the item's position, for example to add a separator after every item but the last:

    text
    @post(team.name)@post(team.name).is_last().then("").else(" · ")

The visibility rules Is first loop item and Is last loop item do the same for whole blocks.

Without a loop ​

You don't always need a loop. @post(team.name).list(", ") joins every name into one line, and @post(photos).count() counts the photos. See VX Script lists.

Limits ​

  • One loop shows at most 200 items, whatever Items to show says.
  • A loop and all the loops nested inside it show at most 5,000 items in total.
  • A single image or a single relation isn't a list, so it can't be looped. Bind it directly.
  • Query Loop can't use a VX list as its source. Inside a Query Loop, dynamic tags read the post the Query Loop is showing.
Technical details for LLMs
  • Stored: the block's vxframeworkLoop attribute (source expression, limit, offset). Any block can carry it; the loop renders the block once per item before visibility runs.
  • Sources: any catalog node with loopable: true: list nodes (repeater, list, multiselect, checkboxes), multi-file media (gallery), and relations with multiple. Single-value relations and single media aren't loopable.
  • Also loopable: table, content_sections, recurring entries / upcoming / previous, and files.
  • Resolution: loop levels are keyed by source path; a tag resolves at the level it names. An aggregator inside a loop collapses only below the pinned item (@post(team.links.url).count() in a team loop counts this member's links).
  • Caps: 200 items per loop, 5,000 per loop tree, regardless of limit.
  • Preview: vx-framework/v1/dynamic-data/loop-preview. Block documents: an inner loop over the same source as its ancestor is flagged by document checks.

Documentation for the VX Framework.