Flow Control

Debouncing, conditionals, and sequences

Flow Control Actions

Actions for controlling execution flow and timing.

debounced_action

Debounces action execution to prevent rapid repeated calls.

Syntax

json
{
  "type": "debounced_action",
  "key": "search",
  "delay": 300,
  "action": [
    { "type": "call_api", "api": "search" }
  ]
}

Properties

PropertyTypeRequiredDescription
keystringYesUnique identifier for debounce group
delaynumberYesDelay in milliseconds
actionarrayYesActions to execute after delay

Examples

Search input debouncing:

json
{
  "type": "Field",
  "fieldType": "text",
  "name": "search",
  "placeholder": "Search...",
  "events": {
    "on_change": [
      {
        "type": "debounced_action",
        "key": "searchInput",
        "delay": 300,
        "action": [
          { "type": "call_api", "api": "search", "params": { "q": "{{$value}}" } }
        ]
      }
    ]
  }
}

Auto-save:

json
{
  "type": "Form",
  "id": "editor",
  "events": {
    "on_change": [
      {
        "type": "debounced_action",
        "key": "autoSave",
        "delay": 1000,
        "action": [
          { "type": "call_api", "api": "saveDraft", "params": { "content": "{{form.editor}}" } },
          { "type": "show_toast", "message": "Draft saved", "level": "success", "duration": 1500 }
        ]
      }
    ]
  }
}

Resize handler:

json
{
  "events": {
    "onResize": [
      {
        "type": "debounced_action",
        "key": "resize",
        "delay": 150,
        "action": [
          { "type": "update_state", "path": "layout", "value": "{{$window.innerWidth < 768 ? 'mobile' : 'desktop'}}" }
        ]
      }
    ]
  }
}

conditional

Executes actions based on conditions.

Syntax

json
{
  "type": "conditional",
  "condition": "{{state.count > 10}}",
  "then": [
    { "type": "show_toast", "message": "Count exceeded!" }
  ],
  "else": [
    { "type": "show_toast", "message": "Count is within limits" }
  ]
}

Properties

PropertyTypeRequiredDescription
conditionstringYesCondition expression
thenarrayYesActions if condition is true
elsearray-Actions if condition is false

Examples

Simple condition:

json
{
  "type": "conditional",
  "condition": "{{state.user.role === 'admin'}}",
  "then": [
    { "type": "navigate", "route": "/admin" }
  ],
  "else": [
    { "type": "navigate", "route": "/dashboard" }
  ]
}

Validation check:

json
{
  "type": "Button",
  "text": "Submit",
  "events": {
    "on_click": [
      {
        "type": "conditional",
        "condition": "{{form.myForm.$valid}}",
        "then": [
          { "type": "call_api", "api": "submit" }
        ],
        "else": [
          { "type": "show_toast", "message": "Please fix validation errors", "level": "warning" }
        ]
      }
    ]
  }
}

Multiple conditions (nested):

json
{
  "type": "conditional",
  "condition": "{{state.status === 'pending'}}",
  "then": [
    { "type": "show_toast", "message": "Please wait...", "level": "info" }
  ],
  "else": [
    {
      "type": "conditional",
      "condition": "{{state.status === 'success'}}",
      "then": [
        { "type": "show_toast", "message": "Success!", "level": "success" }
      ],
      "else": [
        { "type": "show_toast", "message": "Operation failed", "level": "error" }
      ]
    }
  ]
}

Check before action:

json
{
  "type": "conditional",
  "condition": "{{state.hasUnsavedChanges}}",
  "then": [
    {
      "type": "show_dialog",
      "id": "confirmLeave",
      "title": "Unsaved Changes",
      "message": "You have unsaved changes. Do you want to leave?",
      "buttons": [
        { "label": "Stay", "action": [{ "type": "close_dialog", "id": "confirmLeave" }] },
        { "label": "Leave", "action": [{ "type": "navigate", "route": "{{state.targetRoute}}" }] }
      ]
    }
  ],
  "else": [
    { "type": "navigate", "route": "{{state.targetRoute}}" }
  ]
}

sequence

Executes actions in sequence, waiting for each to complete.

Syntax

json
{
  "type": "sequence",
  "actions": [
    { "type": "set_loading", "key": "process", "value": true },
    { "type": "call_api", "api": "step1" },
    { "type": "call_api", "api": "step2" },
    { "type": "set_loading", "key": "process", "value": false }
  ]
}

Properties

PropertyTypeRequiredDescription
actionsarrayYesActions to execute in order
stopOnErrorboolean-Stop if any action fails (default: true)

Examples

Multi-step process:

json
{
  "type": "sequence",
  "actions": [
    { "type": "set_loading", "key": "import", "value": true },
    { "type": "update_state", "path": "importStatus", "value": "Validating..." },
    { "type": "call_api", "api": "validateData" },
    { "type": "update_state", "path": "importStatus", "value": "Importing..." },
    { "type": "call_api", "api": "importData" },
    { "type": "update_state", "path": "importStatus", "value": "Complete!" },
    { "type": "show_toast", "message": "Import successful!", "level": "success" },
    { "type": "set_loading", "key": "import", "value": false }
  ]
}

Continue on error:

json
{
  "type": "sequence",
  "stopOnError": false,
  "actions": [
    { "type": "call_api", "api": "syncService1" },
    { "type": "call_api", "api": "syncService2" },
    { "type": "call_api", "api": "syncService3" },
    { "type": "show_toast", "message": "Sync completed", "level": "success" }
  ]
}

With delays:

json
{
  "type": "sequence",
  "actions": [
    { "type": "show_toast", "message": "Starting...", "level": "info" },
    { "type": "call_api", "api": "longOperation" },
    { "type": "show_toast", "message": "Processing complete!", "level": "success" }
  ]
}

Common Patterns

Debounced Search with Loading

json
{
  "type": "Field",
  "fieldType": "text",
  "name": "search",
  "placeholder": "Search...",
  "events": {
    "on_change": [
      { "type": "update_state", "path": "searchQuery", "value": "{{$value}}" },
      {
        "type": "debounced_action",
        "key": "search",
        "delay": 300,
        "action": [
          { "type": "set_loading", "key": "searching", "value": true },
          {
            "type": "call_api",
            "api": "search",
            "params": { "q": "{{state.searchQuery}}" },
            "onComplete": [
              { "type": "set_loading", "key": "searching", "value": false }
            ]
          }
        ]
      }
    ]
  }
}

Role-Based Actions

json
{
  "type": "Button",
  "text": "Delete",
  "events": {
    "on_click": [
      {
        "type": "conditional",
        "condition": "{{state.user.permissions.includes('delete')}}",
        "then": [
          {
            "type": "show_dialog",
            "id": "confirmDelete",
            "title": "Delete Item",
            "message": "Are you sure?",
            "buttons": [
              { "label": "Cancel", "action": [{ "type": "close_dialog", "id": "confirmDelete" }] },
              { "label": "Delete", "variant": "destructive", "action": [{ "type": "call_api", "api": "delete" }] }
            ]
          }
        ],
        "else": [
          { "type": "show_toast", "message": "You don't have permission to delete", "level": "error" }
        ]
      }
    ]
  }
}

Multi-Step Wizard Submission

json
{
  "type": "sequence",
  "actions": [
    { "type": "set_loading", "key": "wizard", "value": true },
    { "type": "validate_form", "formId": "step1Form" },
    { "type": "validate_form", "formId": "step2Form" },
    { "type": "validate_form", "formId": "step3Form" },
    {
      "type": "call_api",
      "api": "submitWizard",
      "params": {
        "step1": "{{form.step1Form}}",
        "step2": "{{form.step2Form}}",
        "step3": "{{form.step3Form}}"
      }
    },
    { "type": "show_toast", "message": "Wizard completed!", "level": "success" },
    { "type": "navigate", "route": "/success" },
    { "type": "set_loading", "key": "wizard", "value": false }
  ]
}

Smart Auto-Save

json
{
  "type": "Form",
  "id": "document",
  "events": {
    "on_change": [
      { "type": "update_state", "path": "hasUnsavedChanges", "value": true },
      {
        "type": "debounced_action",
        "key": "autoSave",
        "delay": 2000,
        "action": [
          {
            "type": "conditional",
            "condition": "{{form.document.$valid}}",
            "then": [
              { "type": "call_api", "api": "saveDraft", "params": { "content": "{{form.document}}" } },
              { "type": "update_state", "path": "hasUnsavedChanges", "value": false },
              { "type": "update_state", "path": "lastSaved", "value": "{{$now}}" }
            ]
          }
        ]
      }
    ]
  }
}

Best Practices

  1. Use unique debounce keys - Prevent conflicts between debounced actions
  2. Choose appropriate delays - 150-300ms for UI, 500-1000ms for expensive operations
  3. Handle all branches - Always provide else for important conditionals
  4. Keep sequences focused - Break long sequences into smaller logical groups
  5. Combine with loading states - Show progress during multi-step operations
  6. Consider error handling - Decide if sequence should stop on errors