How to navigate to the correct record page from a Search Input in UI Builder?

ronro2
Tera Contributor
Hi everyone,
 
I’m building a Search Input component in UI Builder that allows users to search for tasks. I’ve already created a Search Configuration that works, but I need help with the next step:
 
Goal:
When I type a case number in the search field and select a result, I want to navigate directly to the correct Record Page for that task.
 
Challenge:
The tasks are stored in three different tables, which are child tables of custom table called x_vgll_rail_task:
  • x_vgll_rail_request
  • x_vgll_rail_ticket
  • x_vgll_rail_demand
Each table has its own record page i UI Builder, for example:
https://<instance>/x/vgll/ass-workspace/rail-ticket-record-page/x_vgll_rail_ticket/-1
https://<instance>/x/vgll/ass-workspace/rail-demand-record-page/x_vgll_rail_demand/-1
https://<instance>/x/vgll/ass-workspace/rail-request-record-page/x_vgll_rail_request/-1
When a record is opened, the URL looks like this:
https://<instance>/x/vgll/ass-workspace/rail-request-record-page/x_vgll_rail_request/<sys_id>
 
Question:
How can I configure the Search Input so that when a result is selected, it navigates to the correct record page based on the table name and sys_id?

Can I use a Client Script for this? Is there a best practice approach?
 
I’ve seen an example where they use following actions Knowledge Center workspace:
  • Search executed: Execute Client Script

/**
 * @Param {params} params
 * @Param {api} params.api
 * @Param {any} params.event
 * @Param {any} params.imports
 * @Param {ApiHelpers} params.helpers
 */
function handler({
    api,
    event,
    helpers,
    imports
}) {
    if (event.payload.searchTerm != "") {
        var isAISearchEnabled = api.data.check_ai_search_satus_1.output;
        if (isAISearchEnabled) {
            const fields = {
                searchContextConfigId: event.payload.searchContextConfigId
            };
            const params = {
                searchTerm: event.payload.searchTerm
            };
            helpers.navigate.to('search-results', fields, params, false, false);

        } else {
            const {
                SEARCH_CONSTANTS
            } = imports["sn_km_center.searchInputUtils"]();
            const fields = {
                globalSearchViewConfigId: SEARCH_CONSTANTS.GLOBAL_SEARCH_VIEW_CONFIG_ID
            };
            const params = {
                searchTerm: event.payload.searchTerm,
                selectedSearchContext: 'now/knowledge-center'
            };
            helpers.navigate.to('kc-zing-search', fields, params, false, false);

        }
    }
}​



  • Suggestion item clicked: Execute Client Script
 
/**
* @Param {params} params
* @Param {api} params.api
* @Param {any} params.event
* @Param {any} params.imports
* @Param {ApiHelpers} params.helpers
*/
function handler({api, event, helpers, imports}) {
const { handleNavigation } = imports["sn_km_center.searchInputUtils"]();
    handleNavigation(api, event, helpers);
}
 
 
 
 
My idea:
I’d like to build a script that:
  • Gets the table name and sys_id from the selected item.
  • Navigates to the correct record page using helpers.navigate.to()(I guess?)
Does anyone have an example of how to do this in a simple and best practice way? Or if you could take inspiration of the example provided? 

Alternatively, how would you handle it if you want this to work directly on the search term (without clicking a suggestion)?

Summary:

  • Three different tables, three different record pages.
  • Need to navigate based on table name and sys_id.
  • Open to best practice tips (Client Script, imports, or other approaches).
Thanks in advance guys!!
1 ACCEPTED SOLUTION

You’re not wrong to think it feels redundant — the confusion is just that in UI Builder “Execute client script” isn’t an event by itself. It’s an action that only runs when you hook it up to an event.

So you don’t really choose between:

  • Content items selected

  • Execute client script

Instead it’s:

Content items selected (event) → Execute client script (action) → your code runs

That’s why when you tried “only Execute client script,” nothing happened — there was nothing triggering it.

Do you need both events?

Only if you want both behaviors:

  • Content items selected = user clicks/selects an item from the suggestions dropdown

  • Search executed = user hits Enter / submits the search

If you want redirect on both click and Enter, you’ll typically wire up both events, but you can reuse the same script (or call a shared function/include to avoid duplicating code).

Why your code isn’t redirecting right now

With the newer UI Builder versions, Content items selected usually returns an array, not payload.item. So your script never finds an item and exits silently.

Try this slight tweak (same logic, just grabs the selected item correctly):

function handler({ event, helpers }) {
  const payload = event.payload || {};
  const item = (payload.items && payload.items[0]) || payload.item;

  if (!item) return;

  const sysId = item.sys_id;
  const table = item.table || item.sys_class_name;

  const pageByTable = {
    x_vgll_rail_ticket:  "rail-ticket-record-page",
    x_vgll_rail_demand:  "rail-demand-record-page",
    x_vgll_rail_request: "rail-request-record-page"
  };

  const page = pageByTable[table];
  if (!page || !sysId) return;

  helpers.navigate.to(page, { table, sys_id: sysId });
}

What I’d recommend

  • If you only care about clicking a suggestion: just use Content items selected → Execute client script

  • If you want Enter to work too: add Search executed → Execute client script as well.

 

@ronro2 - Please mark as Accepted Solution and Thumbs Up if you find Helpful!!

 

View solution in original post

8 REPLIES 8

Matthew_13
Mega Sage

Hi Buddy!

YES — this is definitely doable and the cleanest approach is exactly what you mentioned: use “Suggestion item clicked → Execute Client Script” and navigate based on the table name + sys_id returned in the selected result.

My recommended approach:

  1. Make sure your search config/provider returns these two values in the result payload:

    • the record sys_id

    • the record table (or class/table name)

  2. In the Search Input component, configure:

    • Suggestion item clicked → Execute Client Script

  3. In the client script:

    • read table + sys_id from the selected item

    • map the table to the correct record page route

    • call helpers.navigate.to() to open the record page

Example: (basic simple mapping)

function handler({ event, helpers }) {
  const item = event.payload.item || event.payload.selectedItem || event.payload.suggestion;
  if (!item) return;

  const sysId = item.sys_id;
  const table = item.table;

  const pageByTable = {
    x_vgll_rail_ticket:  "rail-ticket-record-page",
    x_vgll_rail_demand:  "rail-demand-record-page",
    x_vgll_rail_request: "rail-request-record-page"
  };

  const page = pageByTable[table];
  if (!page || !sysId) return;

  helpers.navigate.to(page, { table, sys_id: sysId });
}

Thats the generral pattern used in workspaces like similar to the Knowledge Center example except instead of handleNavigation() you’re doing your own navigation logic because you have three different record pages.

For searching without clicking:

For “type case number and hit Enter,” the best practice is:

  • On Search executed, call a small lookup (Data Resource / Scripted API) to resolve the record’s table + sys_id

  • If you get a single exact match → navigate to the record page

  • Otherwise → send them to the search results page

So yes, a Client Script is the right way for the click action, and for “Enter-to-navigate” you typically pair it with a server side lookup to avoid guessing 🙂

 

@ronro2 - Please mark as Accepted Solution and Thumbs Up if you find Helpful!!

@Matthew_13 I think we are close to a solution, thank you!

I used your code that you provided for Search Executed: Open Search Results. 

But I realise there is no option I can choose that is called "Search Item Clicked" as a handler. Maybe due to the new UI Builder update? So what should I choose? 

And I also saw that in the Knowledge Center workspace there is a Client Script Include called "searchInputUtils" attached to both "Search executed" and "Suggestion item clicked" handlers.

How do I configure a client script include for my example If I would need that and what would that script look like? 

There usually isn’t an event literally called “Search item clicked” anymore. For the Search Input component, the event you want is “Suggestion item clicked”. That’s the one that fires when a user selects a record from the type-ahead list.

“Search executed” is more for when the user presses Enter or submits the search, not for selecting a specific result.

Regarding Knowledge Center and the searchInputUtils script you noticed — that’s a good reference. They’re using a UX Client Script Include to centralize the logic and then calling it from multiple handlers (both Search executed and Suggestion item clicked). That’s why you see the same script attached to more than one event.

If you want to follow the same pattern, here’s the general idea:

  • Create your own UX Client Script Include (not a server-side Script Include).

  • Put your navigation logic in there (for example, “given a selected search item, navigate to the correct record page”).

  • In UI Builder, attach Suggestion item clicked → Execute client script.

  • Inside that handler, call your client script include and pass the selected item from the event payload.

  • Optionally, reuse the same script from Search executed if you want consistent behavior when users press Enter.

You don’t have to use a client script include if the logic is very small, but once you need reuse (or want it cleaner, like Knowledge Center), it’s the right approach.

So in short:

  • Use Suggestion item clicked instead of “Search item clicked”

  • Model your setup after Knowledge Center

  • Put the logic in a UX Client Script Include and call it from the handler

That should get you unstuck.

 

More help with script:

 

High level:

  1. Go to UX Client Script Includes (sys_ux_client_script_include) and create a new one.

  2. In your page/client script, add it via “Add a client script include” and then call it using imports["<api_name>"]() inside your handler.

A very simple example of what yours might look like:

UX Client Script Include (example)

  • Name: recordNavUtils

  • Script returns a function you can reuse:

 
function include({ imports }) {
  const pageByTable = {
    x_vgll_rail_ticket:  "rail-ticket-record-page",
    x_vgll_rail_demand:  "rail-demand-record-page",
    x_vgll_rail_request: "rail-request-record-page"
  };

  function navigateToRecord(item, helpers) {
    const sysId = item?.sys_id;
    const table = item?.table || item?.sys_class_name;
    const page = pageByTable[table];

    if (!sysId || !page) return;
    helpers.navigate.to(page, { table, sys_id: sysId });
  }

  return { navigateToRecord };
}

Suggestion item clicked handler (example)

 

 
function handler({ event, helpers, imports }) {
  const { navigateToRecord } = imports["<your_scope>.recordNavUtils"](); // API name
  const item = event.payload.item || event.payload.selectedItem || event.payload.suggestion;
  navigateToRecord(item, helpers);
}

This mirrors what Knowledge Center is doing with sn_km_center.searchInputUtils—they just wrapped navigation logic into a reusable include and called it from both handlers.

 

@ronro2 - Please mark as Accepted Solution and Thumbs Up if you find Helpful!!

@Matthew_13 sorry, it was a typo. When I wrote "Search Item Clicked" I meant "Suggestion item clicked". 

There is nothing called "Suggestion item clicked" anymore. What I can find is something called "Content items selected". Is this it? 🤔