Portal Community

Navigate Action Basics

Any widget that fires an action (buttons, links, form submissions, workflow result handlers) can use a navigate action to move the user to another AppPage or external URL:

// Navigate action on a Button widget
{
  "type": "navigate",
  "target": "/leads/{{ row.id }}",    // Route path or pageId
  "params": {                          // Additional query string params
    "returnUrl": "{{ route.currentPath }}"
  },
  "mode": "push"                       // "push" | "replace" | "new-tab"
}

Target Options

Target formatExampleBehavior
Route path/leads/{{ row.id }}Navigate to the AppPage whose route matches the path
pageIdlead-detailNavigate to the AppPage with that pageId (route params filled from current context)
Absolute URLhttps://example.comNavigate to an external URL (opens in new tab by default)
Relative path../listNavigate relative to the current route base

Navigation Mode: push vs. replace

The mode property controls browser history behavior:

// push (default) — adds a new entry to browser history
// Back button returns to the current page
{
  "type": "navigate",
  "target": "/leads/{{ row.id }}",
  "mode": "push"
}

// replace — replaces the current history entry
// Back button skips the current page (useful for wizard steps)
{
  "type": "navigate",
  "target": "/leads/{{ row.id }}/step-2",
  "mode": "replace"
}

// new-tab — opens the target in a new browser tab
{
  "type": "navigate",
  "target": "/leads/{{ row.id }}",
  "mode": "new-tab"
}

Navigating with Parameters

Pass additional query parameters alongside the route:

// Navigate to edit page with a return URL
{
  "type": "navigate",
  "target": "/leads/{{ row.id }}/edit",
  "params": {
    "returnUrl": "/leads",
    "source": "list-view"
  }
}
// Results in: /app/acme/crm/leads/lead-456/edit?returnUrl=%2Fleads&source=list-view

// Reading the param on the edit page:
{{ route.returnUrl }}   →   "/leads"
{{ route.source }}      →   "list-view"

Conditional Navigation

Use the conditional action type to choose between navigation targets based on a runtime expression:

// Navigate to different pages based on lead status
{
  "type": "conditional",
  "condition": "{{ row.status === 'qualified' }}",
  "then": {
    "type": "navigate",
    "target": "/opportunities/new",
    "params": { "sourceLeadId": "{{ row.id }}" }
  },
  "else": {
    "type": "navigate",
    "target": "/leads/{{ row.id }}/nurture"
  }
}

Navigate After Workflow Completion

Chain a navigate action after a workflow succeeds or fails:

// Button that triggers a workflow, then navigates on success
{
  "type": "chain",
  "actions": [
    {
      "type": "trigger-workflow",
      "workflowId": "CreateLead",
      "inputMapping": {
        "name": "{{ variables.leadName }}",
        "email": "{{ variables.leadEmail }}"
      },
      "outputVariable": "createResult"
    },
    {
      "type": "conditional",
      "condition": "{{ workflowOutput.createResult.success }}",
      "then": {
        "type": "navigate",
        "target": "/leads/{{ workflowOutput.createResult.leadId }}",
        "mode": "replace"    // replace so back button goes to list, not the form
      },
      "else": {
        "type": "set-variable",
        "variable": "errorMessage",
        "value": "{{ workflowOutput.createResult.error }}"
      }
    }
  ]
}

Navigate After Form Submit

// Form widget — navigate on successful submission
{
  "widgetId": "lead-form",
  "type": "Form",
  "config": {
    "submitAction": {
      "type": "chain",
      "actions": [
        { "type": "submit-form", "formId": "lead-form" },
        {
          "type": "navigate",
          "target": "{{ route.returnUrl ?? '/leads' }}",
          "mode": "replace"
        }
      ]
    }
  }
}

Navigating to Home

// Navigate to app home page (isHome: true AppPage)
{
  "type": "navigate",
  "target": "/"
}

// Navigate to a specific named page using pageId shorthand
{
  "type": "navigate",
  "target": "dashboard"    // resolves to the "dashboard" AppPage's route
}

Using returnUrl Pattern

A common UX pattern passes a returnUrl so the user is sent back to where they came from after completing an action:

// Step 1 — on the list page, navigate to edit and pass returnUrl
{
  "type": "navigate",
  "target": "/leads/{{ row.id }}/edit",
  "params": { "returnUrl": "/leads" }
}

// Step 2 — on the edit page, use returnUrl to go back after save
{
  "type": "navigate",
  "target": "{{ route.returnUrl ?? '/leads' }}",
  "mode": "replace"
}

// Using the nullish coalescing operator ensures a safe fallback
// if returnUrl is not present in the URL
History Tip Use "mode": "replace" on wizard-step transitions and post-save redirects so the browser back button skips intermediate steps and returns users to the logical origin page.