# 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:

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

This action can be used in:

* **Button actions**
* **Form submissions**
* **Hook responses**
* **Navigation menu items**

### Navigation Button Examples

#### Basic Page Navigation

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

#### Navigation with Data

Pass data to the destination page using query parameters:

```json
{
  "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:

```json
{
  "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:

```json
{
  "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**

### Navigation Slugs (URL Mapping)

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

```json
{
  "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

### Navigation Menu Schema

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

```json
[{
  "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"
  }]
}]
```

### Navigation Menu Structure

**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

### Dropdown Menus

Create hierarchical navigation with nested menus:

```json
[{
  "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:

```json
[{
  "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:

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

### Navigation with Badges

Add dynamic badges to navigation items:

```json
[{
  "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:

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

**In JavaScript/HTML:**

```javascript
// 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:

   ```json
   {
     "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**:

   ```json
   [{
     "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-Triggered Scripts

Navigation can trigger FileMaker scripts using actions:

```json
{
  "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:

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

## Troubleshooting Common Issues

### Navigation Not Working

* 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:

* **Implement data tables** - See [4.3 Displaying Data in Tables](/getting-started/ide-quick-tour/4.-common-customizations-and-expanding-your-app/4.3-displaying-data-in-tables-page-builder-and-element-config.md)
* **Style your navigation** - See [4.4 Basic App Styling](/getting-started/ide-quick-tour/4.-common-customizations-and-expanding-your-app/4.4-basic-app-styling-site-styling-ui.md)
* **Learn about authentication** - See [Authentication](/reference/authentication.md)

{% hint style="info" %}
**URL Best Practice:** Always use navigation slugs instead of direct page IDs for better maintainability and user experience.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.klai.studio/getting-started/ide-quick-tour/4.-common-customizations-and-expanding-your-app/4.2-implementing-page-navigation-actions-and-site-navigation-ui.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
