Skip to content
  • There are no suggestions because the search field is empty.

Power Plus - List Module

The central engine module that connects a datasource to a renderer, manages paging, handles browser history and URL parameters, coordinates all filter/sort/search controls, and provides a debug mode that prints the available data schema to the browser console.

The List module is the core engine of the Power Plus framework. I t coordinates the datasource (which provides the data), the renderer (which displays it), and all the controls (which let visitors interact with it).

When a page loads, the List module:
1. Discovers its datasource and renderer by looking up their names in the plugin registry.
2. Waits for all connected controls (filters, sort, search) to finish initializing.
3. Builds a request object from the combined state of all controls.
4. Asks the datasource to fetch data matching that request.
5. Passes the results to the renderer for display.
6. Manages paging, loading states, error states, empty states, and browser history.

Configuration

Field

Type

Description

Name

Text

A unique identifier for this list instance (e.g. product_list, jobs_list). All controls (filters, sort, search) reference this name to connect themselves to this list. The name must contain only letters, numbers, hyphens, and underscores.

Renderer Name

Text

Must exactly match the Name field of a Renderer module placed somewhere on the same page. If no renderer with this name is found, the list will show an error.

Datasource Name

Text

Must exactly match the Name field of a Datasource module placed somewhere on the same page. If no datasource with this name is found, the list will show an error.

Paging

Choice

Controls how additional results are loaded. Disabled — all matching items are shown at once (only suitable for small datasets). Button — a “Load More” button appears at the bottom. Auto — items load automatically as the visitor scrolls down (infinite scroll).

URL Paging (SEO)

Boolean

When enabled, the current page number is appended to the URL as a query parameter (e.g. ?page=2). This is important for SEO because it allows search engines to discover and index each page of results as a separate URL. The “Load More” button also becomes a proper <a> link with an href, which search engine crawlers can follow.

URL Paging Parameter

Text

The name of the URL query parameter used for paging. Default: page. You might change this if you have multiple lists on the same page and need to avoid parameter name conflicts.

Selection

Choice

Enables item selection behavior. Disabled — items are not selectable (the default for most use cases). Single — clicking an item selects it (and deselects the previous one). Multi — clicking items toggles their selection. This is used by advanced integrations like the Wishlist, where selected items can be passed to another component.

Default Filters

You can add default filters directly in the List module. These filters are always applied to every request — they cannot be changed or removed by the visitor. They are combined with any visitor-facing filter controls using AND logic.

This is useful for pre-filtering data. For example, on a “Featured Products” page, you might add a default filter is_featured == true so only featured items ever appear, regardless of what other filters the visitor selects.

Filter Field

Description

Property Name

The path to the data field to filter on. For HubDB data, this is typically prefixed with values. (e.g. values.featured, values.category.name). For CRM data, use the property name directly (e.g. category, hs_price_eur). The property name can also be a JSONata expression for complex matching.

Operator

The comparison operator. See the Filter Operators Reference for the full list. Common operators: == (exact match), != (not equal), Contains Token (value contains the term), IN (value is in a list).

Value

The value to compare against. This can be a plain string, a number, or a JSONata expression enclosed in [[ ]] brackets for dynamic values. For example, [[$millis()]] evaluates to the current timestamp in milliseconds.

Default Sorts

You can add default sorts that define the initial ordering of results. These are applied when no visitor-selected sort is active, and they are appended after any visitor-selected sorts.

Sort Field

Description

Property Name

The data field to sort by. For HubDB: values.publish_date, values.name, etc. For CRM: name, hs_price_eur, etc.

Order

asc (ascending: A→Z, 0→9, oldest→newest) or desc (descending: Z→A, 9→0, newest→oldest).

Translations / Text

These fields let you customize the text that the list displays in various states. All text fields support rich text (HTML) and JSONata expressions, so you can create dynamic, context-aware messages.

Field

Description

Load Button Text

The label for the “Load More” paging button. Default: Load More. You might change this to something like Show more results or localize it for other languages.

Empty Text

Rich text displayed when the list has zero results after filtering. This is your opportunity to guide the visitor — suggest clearing filters, trying different search terms, or provide a link to reset. Supports JSONata so you can reference the current filter state in the message.

Error Text

Rich text displayed when something goes wrong (network error, invalid data, etc.). In debug mode, technical error details are appended automatically. Supports JSONata with access to the error variable.

Style Options

Field

Description

Min Height

Minimum height of the list container in pixels. Setting this prevents the page from “jumping” while data is loading — the container reserves space even before the first results appear. A value of 200–400px is typical.

Color Scheme

Light or Dark. Applies the POWER THEME’s light or dark color scheme to the list container, including the loading indicator, overlay, and status messages.

Animation

Enable AOS (Animate on Scroll) effects. When enabled, the list container fades or slides into view as the visitor scrolls to it. You can choose the animation type (fade, slide-up, zoom, etc.) and set a delay.

Button Style

The CTA style and size for the “Load More” button. Uses the POWER THEME’s CTA system, so you can choose from all available button styles (solid, outline, ghost, etc.) and sizes (small, regular, large). Also includes alignment options (left, center, right).

How Paging Works

Paging determines how additional results beyond the first page are loaded:

  • Button: After the initial items are rendered, a “Load More” button appears at the bottom of the list. When the visitor clicks it, the next batch of items is fetched and appended below the existing ones. The button disappears when all items have been loaded. This is the recommended default for most use cases because it gives visitors explicit control over when more content loads.

  • Auto (Infinite Scroll): The framework watches for the visitor to scroll near the bottom of the list. When the scroll position reaches the “load more” trigger element, the next batch is fetched and appended automatically. This continues until all items are loaded. Infinite scroll works well for browsing-heavy pages like product catalogs, where visitors tend to scroll continuously.

  • URL Paging (SEO enhancement): When enabled alongside Button or Auto paging, the current page number is written into the URL as a query parameter. For example, after loading the second page, the URL might become ?page=2. This has two benefits: (1) search engines can crawl each page separately, improving SEO for large datasets; (2) visitors can bookmark or share a specific page of results. The “Load More” button gets a proper <a href="?page=3"> link that crawlers can follow.

  • Disabled: All matching items are loaded and rendered in a single request. Only use this for small datasets (under ~50 items) or when the renderer itself handles scrolling (like the Slider renderer).

Debug Mode: Schema Console Output

When you’re setting up a new list, you need to know what data fields are available so you can configure your renderer and filters correctly. The framework provides a built-in debug mode that prints the complete data schema to your browser’s developer console.

How to Activate Debug Mode

Debug mode is active in two situations:

  1. HubSpot Preview — When viewing the page in HubSpot’s page preview (the URL contains hubspotpreview).

  2. Debug URL Parameter — When viewing the live page with ?hsDebug=true appended to the URL (the hs_preview parameter must also be present).

What Gets Logged

When debug mode is active, the framework logs several things to the browser console every time data is loaded:

1. Available JSONata Placeholders

Each renderer prints a formatted list of all available data fields, their types, and the exact [[ ... ]] placeholder syntax you can use in your renderer configuration. Open your browser’s developer console (F12 → Console tab) and look for a message like:

Available JSONata placeholders in Block Renderer 'product_renderer' :
string [[ object.id ]]
string [[ object.name ]]
string [[ object.hs_price_eur ]]
string [[ object.hs_sku ]]
string [[ object.description ]]
string [[ object.category ]]
string [[ object.hs_images ]]

For HubDB datasources, the output shows the nested values structure:

Available JSONata placeholders in Block Renderer 'card_renderer' :
string [[ object.id ]]
string [[ object.createdAt ]]
string [[ object.updatedAt ]]
object [[ object.values ]]
string [[ object.values.name ]]
string [[ object.values.description ]]
object [[ object.values.image ]]
string [[ object.values.image.url ]]
string [[ object.values.image.altText ]]
object [[ object.values.category ]]
string [[ object.values.category.id ]]
string [[ object.values.category.name ]]
string [[ object.values.category.label ]]
boolean [[ object.values.featured ]]
string [[ object.values.link ]]
[object] [[ object.values.tags ]]
string [[ object.values.tags[0].name ]]
string [[ object.values.tags[0].label ]]

The format is: type followed by the exact placeholder expression you can copy-paste into your renderer field configuration. Array types are shown as [type] and include an example accessor with [0].

2. Current State

After each data load, the console logs the current list state object:

New State:
{ filters: { category_filter: ["electronics"], size_filter: ["large"] }, sorts: { product_sort: ["price_asc"] } }

This shows exactly which filter options and sort options are currently selected, which is helpful for debugging state management issues.

3. Error Details

When an error occurs in debug mode, detailed error information is shown both in the console and appended to the on-page error message. This includes: - The error message - The problematic token (for JSONata expression errors) - The position in the expression where the error occurred - The error code

This makes it much easier to diagnose issues like typos in JSONata expressions or misconfigured property names.

Using the Schema Output to Configure Your Page

Here’s the recommended workflow for setting up a new list:

  1. Add the datasource module to your page and configure it with the URL/table.

  2. Add any renderer module to the page (even with default/empty field configuration).

  3. Add the List module and wire them together by name.

  4. Preview the page in HubSpot (or open it with ?hsDebug=true).

  5. Open the browser console (F12 → Console) and look for the “Available JSONata placeholders” message.

  6. Copy the placeholder expressions you need and paste them into your renderer field configuration.

  7. For filters, look at the schema output to find the correct Property Name paths (e.g. values.category.name for a HubDB dropdown column).

This is especially valuable when working with: - External APIs where you’re not sure of the exact response structure - HubDB tables with many columns and nested types (images, dropdowns, multi-selects) - CRM objects where property names may not be obvious - JSONata-transformed data where the output shape depends on your query

Disabling Debug Mode in Production

Debug mode is never active on production pages viewed by regular visitors. It only activates in HubSpot’s preview environment or when the specific debug URL parameters are present. There is nothing you need to do to disable it — it’s off by default.

Additionally, caching is disabled in debug mode. CRM and Cision datasources normally cache responses in memory and localStorage to reduce API calls, but in debug mode all caching is bypassed so you always see fresh data during development.

Examples

Basic Product List

The simplest configuration: a CRM datasource, a block renderer, and infinite scroll paging.

List Module:
Name: product_list
Datasource Name: product_datasource
Renderer Name: product_renderer
Paging: Auto (infinite scroll)

When combined with a CRM datasource (endpoint: products/list) and a Block renderer configured with product image, name, and price fields, this creates a scrollable product catalog.

Featured Items Only (Pre-Filtered)

Show only items where the featured checkbox is enabled. This is useful for hero sections or curated spotlights on a homepage.

List Module:
Name: featured_list
Datasource Name: hubdb_datasource
Renderer Name: featured_renderer
Paging: Disabled
Filters:
- Property Name: values.featured
Operator: ==
Value: 1

Because paging is disabled, all matching featured items appear at once. The default filter ensures only featured items are shown — visitors cannot override this.

Related Products (Exclude Current)

On a product detail page, show products from the same category but exclude the product currently being viewed. This uses HubL template variables ( and ) that HubSpot resolves at page render time.

List Module:
Name: related_products
Datasource Name: product_datasource
Renderer Name: product_renderer
Filters:
- Property Name: category
Operator: ==
Value:
- Property Name: id
Operator: !=
Value:

The two default filters work together: the first includes only products in the same category, and the second excludes the current product so it doesn’t appear in its own “related” section.

Custom Empty State with Reset Action

Use JSONata and HTML in the empty text to create a helpful, interactive message when no results match:

Empty Text:
<h4>No results found.</h4>
<p>We couldn't find anything matching your current filters and search.
Try adjusting your selections or
<a class="listStateButton" state="{}">clear all filters</a>
to start over.</p>

The special CSS class listStateButton combined with the state="{}" attribute creates a clickable link inside the empty message that resets all filter, sort, and search state when clicked. The {} empty object means “clear everything”. You can also use inputValueButton with inputQuery and value attributes to set specific form input values from within the message.

Custom Error State with Context

Error Text:
<h4>Something went wrong.</h4>
<p>We had trouble loading the data. Please try again in a few moments.</p>

In debug mode, the framework automatically appends technical error details (message, token, position) below this text, which helps developers diagnose issues without needing to open the console.

State Management

The List module maintains a comprehensive state management system that tracks the selections of all connected controls and synchronizes them across browser history and URL parameters.

How State Flows

When any control changes (a filter is selected, a sort is chosen, a search term is entered):

  1. The list collects the current state from every connected control by calling each control’s appendRequest() method.

  2. It builds a combined request object with filter groups, sorts, and query text.

  3. It pushes the new state into the browser history (via window.history.pushState()), so the back button works.

  4. If any controls have URL parameters enabled, the URL is updated with the new parameter values.

  5. The list sends the request to the datasource and renders the results.

Browser History Integration

When a visitor uses the browser’s back and forward buttons, the list intercepts the popstate event, restores the previous state to all controls, and reloads the data. This means filter selections, sort choices, and search terms are all preserved through navigation.

URL Parameters

Controls can optionally store their state in URL query parameters. This makes filtered views shareable — a visitor can copy the URL (e.g. https://yoursite.com/products?category=shoes&sort=price_asc&q=running) and share it. When someone opens that URL, the list automatically restores all the control states from the parameters.

To enable URL parameters for a control, set Use in URL to true and provide a URL Parameter Name. Choose short, descriptive names: category, sort, q, page, etc.

State Listeners (Showing/Hiding Sections)

Other page elements can react to the list’s current state (loading, loaded, empty, error) using CSS classes. Add the class pwr-list-state-listener--{list_name} to any HTML element, and the framework will automatically add one of these state classes:

  • pwr-list-state--loading — data is currently being fetched

  • pwr-list-state--loaded — data has been loaded and rendered

  • pwr-list-state--empty — the data loaded successfully but zero items matched

  • pwr-list-state--error — an error occurred during loading

The most common use is hiding a section when the list is empty:

.pwr-list-state-listener--wishlist { display: none; }
.pwr-list-state-listener--wishlist:not(.pwr-list-state--empty) { display: block; }

This CSS hides the element by default, then shows it when the list has results (is not in the empty state). The Wishlist uses this pattern to hide the “Get A Quote” button and the “Recommended Products” section when the cart is empty — there’s no point showing a checkout button if there’s nothing in the cart.

You can also use this to show different content during loading:

.pwr-list-state-listener--my_list.pwr-list-state--loading .loading-message { display: block; }
.pwr-list-state-listener--my_list.pwr-list-state--loaded .loading-message { display: none; }

JavaScript Events

The list also dispatches custom DOM events that you can listen for in custom JavaScript:

  • onListLoading — fired when the list starts loading data

  • onListLoaded — fired when data has been loaded and rendered

  • onListEmpty — fired when zero results are returned

  • onListError — fired when an error occurs

  • onListReload — fired when the list is asked to reload (by a control change)