4.2 Implementing Page Navigation (Actions & Site Navigation UI)

Navigation is a crucial aspect of any BetterForms application. This section covers both programmatic navigation using actions and setting up site-wide navigation menus that users can interact with.

Two Types of Navigation in BetterForms

1. Action-Based Navigation

Navigation triggered by user actions (button clicks, form submissions, etc.)

2. Site Navigation Menu

Persistent navigation menus that appear on all pages (typically in the sidebar)

Action-Based Navigation

Using the path Action

The path action is the primary way to navigate between pages programmatically:

{
  "action": "path",
  "options": {
    "path": "/dashboard"
  }
}

This action can be used in:

  • Button actions

  • Form submissions

  • Hook responses

  • Navigation menu items

Basic Page Navigation

{
  "type": "button",
  "text": "Go to Dashboard",
  "buttonClasses": "btn btn-primary",
  "styleClasses": "col-md-4",
  "actions": [{
    "action": "path",
    "options": {
      "path": "/dashboard"
    }
  }]
}

Pass data to the destination page using query parameters:

{
  "type": "button",
  "text": "Edit Contact",
  "buttonClasses": "btn btn-info",
  "styleClasses": "col-md-4",
  "actions": [{
    "action": "path",
    "options": {
      "path": "/contact-edit?id=123&mode=edit"
    }
  }]
}

External Navigation

Link to external websites:

{
  "type": "button",
  "text": "Open Documentation",
  "buttonClasses": "btn btn-secondary",
  "styleClasses": "col-md-4",
  "actions": [{
    "action": "path",
    "options": {
      "url": "https://docs.fmbetterforms.com/"
    }
  }]
}

Save and Navigate Pattern

Common FileMaker developer pattern - save data then navigate:

{
  "type": "button",
  "text": "Save & Return",
  "buttonClasses": "btn btn-success",
  "styleClasses": "col-md-4",
  "actions": [
    {
      "action": "runUtilityHook",
      "options": {
        "type": "save"
      }
    },
    {
      "action": "path",
      "options": {
        "path": "/contact-list"
      }
    }
  ]
}

Setting Up Site Navigation in the IDE

Where to Configure Site Navigation

  1. Open App Settings in the BetterForms IDE

  2. Navigate to Environment section

  3. Find the Navigation tab

  4. Configure your navigation schema

First, set up navigation slugs to map friendly URLs to page IDs:

{
  "default": {
    "id": "36D74465-3F11-4CE4-A0FD-370D78C98B86"
  },
  "dashboard": {
    "id": "633D7D10-F8AD-4B6E-8D86-BDC8038D6E91"
  },
  "contacts": {
    "id": "A1B2C3D4-E5F6-7890-1234-567890ABCDEF"
  },
  "settings": {
    "id": "F1E2D3C4-B5A6-9876-5432-10FEDCBA9876"
  }
}

Benefits of Navigation Slugs:

  • Clean URLs: /dashboard instead of /form/633D7D10-F8AD-4B6E-8D86-BDC8038D6E91

  • Easy Updates: Change the page ID in one place to update all references

  • User-Friendly: URLs are easier to understand and remember

The navigation menu is defined as an array of objects in the Menu Schema section:

[{
  "sectionLabel": "Main Menu",
  "subs": [{
    "label": "Dashboard",
    "icon": "fa fa-home",
    "path": "/dashboard"
  }, {
    "label": "Contacts",
    "icon": "fa fa-users",
    "path": "/contacts"
  }, {
    "label": "Settings",
    "icon": "fa fa-cog",
    "path": "/settings"
  }]
}]

Top Level Properties:

  • sectionLabel: Section title (not clickable)

  • subs: Array of menu items

  • styleClassesSection: CSS classes for the section

Menu Item Properties:

  • label: Display text

  • icon: Font Awesome icon class

  • path: Navigation path (corresponds to slugs)

  • actions: Alternative to path for complex behaviors

  • visible: Boolean or visible_calc for conditional display

Advanced Navigation Examples

Create hierarchical navigation with nested menus:

[{
  "sectionLabel": "Main Menu",
  "subs": [{
    "label": "Dashboard",
    "icon": "fa fa-home",
    "path": "/dashboard"
  }, {
    "label": "Contacts",
    "icon": "fa fa-users",
    "subs": [{
      "label": "View All Contacts",
      "icon": "fa fa-list",
      "path": "/contacts"
    }, {
      "label": "Add New Contact",
      "icon": "fa fa-plus",
      "path": "/contact-new"
    }, {
      "divider": true
    }, {
      "label": "Import Contacts",
      "icon": "fa fa-upload",
      "path": "/contact-import"
    }]
  }]
}]

Action-Based Navigation Items

Use actions instead of direct navigation for complex behaviors:

[{
  "sectionLabel": "Main Menu",
  "subs": [{
    "label": "Logout",
    "icon": "fa fa-sign-out",
    "actions": [{
      "action": "authLogout"
    }, {
      "action": "path",
      "options": {
        "path": "/login"
      }
    }]
  }]
}]

Conditional Navigation

Show navigation items based on user permissions:

[{
  "sectionLabel": "Main Menu",
  "subs": [{
    "label": "Admin Panel",
    "icon": "fa fa-shield",
    "path": "/admin",
    "visible_calc": "app.user.role === 'admin'"
  }]
}]

Add dynamic badges to navigation items:

[{
  "sectionLabel": "Main Menu",
  "subs": [{
    "html": "<a href=\"/#/messages\" title=\"Messages\">\n    <i class=\"fa fa-envelope\"></i> Messages\n    <span class=\"pull-right badge badge-danger\">{{app.unreadCount}}</span>\n</a>"
  }]
}]

URL Structure and Query Parameters

BetterForms URL Structure

https://yourdomain.fmbetterforms.com/#/dashboard?id=123&mode=edit

Components:

  • https://yourdomain.fmbetterforms.com - Your domain

  • #/dashboard - Navigation slug

  • ?id=123&mode=edit - Query parameters

Working with Query Parameters

In FileMaker Scripts: Access query parameters via the $$BF_Query global variable:

// In your onFormRequest hook
Set Variable $contactId = JSONGetElement($$BF_Query, "id")
Set Variable $mode = JSONGetElement($$BF_Query, "mode")

In JavaScript/HTML:

// Using BetterForms utility function
const contactId = BF.getQueryParam('id');
const mode = BF.getQueryParam('mode');

IDE Navigation Configuration Workflow

Step 1: Plan Your Navigation Structure

  1. List all pages in your app

  2. Group related pages under logical sections

  3. Determine hierarchy (which pages need submenus)

  4. Consider user roles (which pages need conditional access)

Step 2: Set Up Navigation Slugs

  1. Go to App Settings → Navigation

  2. Find the Slug Names section

  3. Add entries for each page:

    {
      "dashboard": { "id": "your-page-id" },
      "contacts": { "id": "your-page-id" },
      "settings": { "id": "your-page-id" }
    }

Step 3: Configure Menu Schema

  1. In the Menu Schema section

  2. Build your navigation structure:

    [{
      "sectionLabel": "Main Menu",
      "subs": [
        // Your menu items here
      ]
    }]

Step 4: Test Navigation

  1. Save your changes

  2. Test each navigation item

  3. Verify paths resolve correctly

  4. Check conditional visibility

Best Practices

1. Consistent Navigation Structure

  • Keep navigation consistent across all pages

  • Use familiar icons and terminology

  • Group related functionality together

2. User-Friendly URLs

  • Use descriptive navigation slugs

  • Avoid exposing internal page IDs

  • Keep URLs short and memorable

3. Responsive Design

  • Consider mobile navigation experience

  • Use appropriate icons for touch interfaces

  • Test navigation on different screen sizes

4. Performance Optimization

  • Minimize navigation complexity

  • Use conditional visibility judiciously

  • Consider caching navigation data

Integration with FileMaker

Navigation can trigger FileMaker scripts using actions:

{
  "label": "Generate Report",
  "icon": "fa fa-file-pdf",
  "actions": [{
    "action": "runUtilityHook",
    "options": {
      "type": "generateReport",
      "reportType": "monthly"
    }
  }]
}

Dynamic Navigation Updates

Update navigation based on FileMaker data:

{
  "label": "Orders",
  "icon": "fa fa-shopping-cart",
  "path": "/orders",
  "visible_calc": "app.user.permissions.includes('view_orders')"
}

Troubleshooting Common Issues

  • Check that navigation slugs are properly configured

  • Verify page IDs are correct

  • Ensure JSON syntax is valid

Pages Not Loading

  • Confirm target pages exist

  • Check page authentication settings

  • Verify navigation paths match slug names

Conditional Navigation Issues

  • Test visible_calc expressions

  • Verify app model data is available

  • Check for JavaScript syntax errors

Next Steps

Now that you understand navigation, you can:

URL Best Practice: Always use navigation slugs instead of direct page IDs for better maintainability and user experience.

Last updated