Collection prototypes allow you to display items within a collection using different layouts based on their properties, creating more dynamic and context-aware user interfaces.

What are Collection Prototypes?

Collection prototypes are specialized components that define different display formats for items within a single collection. They act as templates that are applied conditionally based on item properties, allowing you to:

  • Display collection items with different layouts based on their data properties
  • Create visually distinct displays for featured or highlighted items
  • Apply specialized formatting for different item types or states
  • Integrate custom components for enhanced functionality
  • Add interactive features like item selection

Collection prototypes always work as child components within a parent Collection component. While a Collection iterates through a data array, Collection Prototypes determine how each individual item should be displayed.

How Collection Prototypes Work

Core Concepts

Collection prototypes use a simple but powerful mechanism to determine which layout to apply to each item:

Prototype Identifier Key

The data property used to determine which prototype to apply (e.g., type, status, priority)

Prototype Identifier Value

The specific value that triggers this prototype layout (e.g., featured, active, high)

When the collection renders, each item is evaluated against all available prototypes. The first prototype whose identifier key and value match the item’s data is used to render that item.

Visual Example

Here’s how collection prototypes can display products with different layouts based on their type property:

Collection with multiple prototypes in action

Implementation Guide

1. Prepare Your Data

Before implementing collection prototypes, you need to prepare the data structure that will determine which prototype applies to each item.

Using a Service Task Node

The most common approach is to use a Service Task node with business rules:

1

Add a Service Task Node

In the FlowX.AI Designer, add a Service Task node before your User Task node and connect them with a sequence flow.

Adding a Service Task node

2

Configure the Business Rule

Select your Service Task node, go to the Business Rules tab, and add a new business rule or edit an existing one.

Configuring a business rule

3

Write the Data Preparation Code

Use JavaScript to create your data structure and assign it to the process context:

// Create the data structure for products
const products = [
{
  "name": "Product One Plus",
  "description": "The plus option",
  "type": "normal",  // This property will determine which prototype to use
  "price": 99.99
},
{
  "name": "Product Two Premium",
  "description": "This is premium product",
  "type": "recommended",  // This will use a different prototype
  "price": 149.99
},
{
  "name": "Product Basic",
  "description": "The most basic option",
  "type": "normal",
  "price": 49.99
}
];

// Add the products array to the process data
output.put("products", products);
4

Test Your Data

Save your configuration, and test your business rule by using the Test Rule feature in the business rules editor to make sure the data is correctly added to the process context.

Verifying business rule output

2. Create the UI Components

Once your data is prepared, you can implement the collection and its prototypes in the UI Designer:

1

Create a User Task Node

In the FlowX.AI Designer, create or select an existing User Task node in your process and click the brush icon to open the UI Designer.

Opening the UI Designer for a User Task node

2

Add a Collection Component

Add a root component (like a Card or Container) to your node, then add a Collection component inside it. Configure the Collection’s source to point to your data array (e.g., products).

Adding a Collection component

The collectionSource property specifies the process key where your list can be found. It should be a valid array of objects. For example, if your data is at processData.products, you would set the source to products.

3

Add Collection Prototypes

For each different display type:

  1. Click on your Collection component to select it
  2. Add a Collection Prototype as a child component
  3. Configure the prototype’s settings:
    • Prototype Identifier Key: The field to check (e.g., type)
    • Prototype Identifier Value: The value to match (e.g., normal)

Configuring a Collection Prototype

  1. (If different prototypes identifier values are needed) Repeat for each different prototype you need, using different identifier values
4

Design Each Prototype's Layout

For each prototype, add the UI components that will display your data:

  1. Select a Collection Prototype
  2. Add components like Text, Image, Button, etc.
  3. Configure each component to use relative paths to the collection item data saved in the Data Model:
    • Use text UI element with the key ${name}
    • Use text UI element with the key ${description}

Adding components to a prototype

Components within a collection use relative paths to the collection source. This means that wherever the collection is found inside the process data, the components inside the collection need their keys configured relative to that collection.

3. Add Interactivity

To make your collection items interactive, such as allowing users to select an item:

1

Create a Node Action

Add an Action to your User task node:

  1. Go back to the process designer
  2. Select your User Task node
  3. Go to the Actions tab
  4. Add a new action with:
    • Type: Manual
    • Name: (e.g., selectItem)

Adding a Node Action

Configuration options:

  • Set as Manual since users trigger it
  • Mark as Mandatory if selection is required to proceed
  • Enable Repeatable for changeable selections
2

Configure a UI Action

Add a UI action to your collection prototype:

  1. Return to the UI Designer
  2. Select the component in your prototype that should trigger the action
  3. In the Settings panel, add a UI Action
  4. Add a Collection Item Save Key.
  5. Add a Custom Key and make sure it matches the Collection Item Save Key.

Adding a UI Action

3

Test the Interaction

Save your changes and test your process to verify that:

  • Different items display with the correct prototype layouts
  • Interactive elements work as expected
  • Selected data is properly saved to your process data

Best Practices

Working with Custom Components

When integrating custom components into collection prototypes, follow these best practices:

  1. Use relative paths for data access

    • Configure input keys relative to collection items
    • Example: Use name instead of app.clients.name
  2. Maintain consistent data structures

    • Ensure required data exists in collection items
    • Follow consistent data patterns across all items

Data Access Patterns

Components use full paths from data root:

// Input keys:
// app.name
// app.signatureImageURL

data: {
    app: {
        name: "John Doe",
        signatureImageURL: "http://example.com/signature1.png"
    }
}

Performance Optimization

  • Limit the number of items in your collection when possible
  • Simplify complex prototype layouts
  • Consider pagination for large data sets
  • Optimize images and other media within prototypes
  • Avoid deeply nested components within prototypes

Pro tips:

  • Test your collection prototypes with various data scenarios
  • Verify data flow through the entire selection process
  • Monitor the process data for correct updates
  • Ensure your UI provides clear visual feedback when an item is selected

Troubleshooting

When working with collection prototypes, you might encounter some common issues:

Common Issues and Solutions

Known Limitations

  • Nested collections (collections inside collection prototypes) may cause performance issues and should be used sparingly
  • Deep data structures might require careful handling of relative paths for proper data binding

Debugging Tips

  1. Use process data inspection:

    • Monitor the process data before and after interactions with collection prototypes
    • Verify that selected items are correctly saved to the expected process data keys
  2. Test with simplified data:

    • Start with a minimal data set to confirm basic functionality
    • Gradually add complexity to identify where issues might occur
  3. Isolate components:

    • Test individual UI components outside the collection context
    • Add components to prototypes one by one to identify problematic elements

Frequently Asked Questions

Code Examples

Different Prototype Layouts Based on Item Status

This example shows how to display items differently based on their status (active, pending, completed):

// Setting up process data with items of different statuses
output.put("processData", {
  "tasks": [
    {
      "id": "task-001",
      "title": "Review application",
      "description": "Initial review of customer application",
      "status": "active",
      "priority": "high"
    },
    {
      "id": "task-002",
      "title": "Verify documents",
      "description": "Check submitted documentation for completeness",
      "status": "pending",
      "priority": "medium"
    },
    {
      "id": "task-003",
      "title": "Send confirmation",
      "description": "Email confirmation to customer",
      "status": "completed",
      "priority": "low"
    }
  ]
});

Multiple Identifier Keys for Complex Conditions

You can use multiple collection prototypes with different identifier keys to handle complex display logic:

// Setting up process data with items having multiple attributes
output.put("processData", {
  "notifications": [
    {
      "id": "notif-001",
      "message": "Your application has been approved",
      "type": "success",
      "priority": "high",
      "read": false
    },
    {
      "id": "notif-002",
      "message": "Please review updated terms",
      "type": "info",
      "priority": "low",
      "read": true
    },
    {
      "id": "notif-003",
      "message": "Action required: Missing information",
      "type": "warning",
      "priority": "high",
      "read": false
    }
  ]
});

Nested Data Structures

Working with nested data in collection prototypes:

// Setting up process data with nested objects
output.put("processData", {
  "orders": [
    {
      "id": "order-001",
      "customer": {
        "name": "John Smith",
        "tier": "premium"
      },
      "items": [
        { "name": "Product A", "quantity": 2 },
        { "name": "Product B", "quantity": 1 }
      ],
      "status": "processing"
    },
    {
      "id": "order-002",
      "customer": {
        "name": "Jane Doe",
        "tier": "standard"
      },
      "items": [
        { "name": "Product C", "quantity": 3 }
      ],
      "status": "shipped"
    }
  ]
});