typeahead docs

Typeahead

Typeahead is an input field with dropdown-like listbox that displays suggested results that most closely match a user's given search term.

Twig Usage
{% include '@bolt-components-typeahead/typeahead.twig' %}
Schema
Note: when assigning component props as HTML attributes on a web component, make sure to use kebab-case.
Prop Name Description Type Default Value Option(s)
attributes

A Drupal-style attributes object with extra attributes to append to this component.

object
max_results

The maximum number of typeahead results to display

number 10
items

An array of objects that's used to populate the suggestion list that appears below the input as the users type. This array of objects can be asynchronously fetched and should contain a label, url, and optionally description.

array
clear_input_text

Screenreader-specific text for the clear search button, intended to provide a longer, more descriptive explanation of the clear button's behavior.

string Clear search results
submit_button_text

Screenreader-specific text for the submit button, intended to provide a longer, more descriptive explanation of the submit button's behavior.

string Submit
input_label

Screenreader-specific label text associated with the search input.

string
input_placeholder

The placeholder text to display inside the Typeahead search input.

string Search
input_value

Initial value to pre-populate the input field

string
input_name

Input element's name attribute used when pre-rendering the component

string
no_highlight

Disable text highlighting in matching search results (highlighting is enabled by default)

boolean false
disabled

Disables input as well as the search and cancel buttons.

boolean false
Install Install
npm install @bolt/components-typeahead
Dependencies @bolt/components-form @bolt/components-icon @bolt/core @bolt/elements-button @bolt/elements-icon @bolt/lazy-queue fuse.js html-react-parser mousetrap react react-autosuggest

Demo: Dyamically Fetch Data

In this example, we populate the Typeahead component with JSON data that's dynamically fetched from an external source via the getSuggestions hook.

Also, this demo caps the max # of search results to display at 5.


{% include "@bolt-components-form/form.twig" with {
  children: include("@bolt-components-typeahead/typeahead.twig", {
    attributes: {
      class: [
        "js-typeahead-hook--dynamically-fetch-data"
      ]
    },
    max_results: 5,
    input_name: "q"
  }),
  attributes: {
    action: "https://www.pega.com/search",
    target: "_blank",
    rel: "noopener",
    method: "GET"
  }
} %}

// NOTE: make sure you're running this code through a tool like Babel before shipping for cross browser compatibility!
const dynamicTypeaheadDemo = document.querySelector(
  '.js-typeahead-hook--dynamically-fetch-data',
);

const setupEventHandlers = () => {
  // note: make sure to let Typeahead know when the data fetched is ready
  dynamicTypeaheadDemo.on('getSuggestions', async (value) => {
    return await new Promise(async (resolve) => {
      await fetch('/build/data/typeahead.data.json')
        .then(function (response) {
          return response.json();
        })
        .then(function (data) {
          return resolve(data);
        });
    });
  });

  dynamicTypeaheadDemo.on('onSelected', (element, event, suggestion) => {
    const exactMatch = element.items.filter(
      (item) => item.label === suggestion.suggestionValue,
    )[0];

    function navigateTo(url) {
      if (window.location !== window.parent.location) {
        const win = window.open(url, '_blank', 'noopener');
        win.focus();
      } else {
        window.location = url;
      }
    }

    if (exactMatch && exactMatch.url) {
      if (exactMatch.url) {
        navigateTo(exactMatch.url);
      } else {
        navigateTo(`https://www.pega.com/search?q=${itemSelected.label}`);
      }
    } else if (suggestion.suggestionValue !== '') {
      navigateTo(`https://www.pega.com/search?q=${suggestion.suggestionValue}`);
    }
  });
};

if (dynamicTypeaheadDemo) {
  if (dynamicTypeaheadDemo._wasInitiallyRendered) {
    setupEventHandlers();
  }

  dynamicTypeaheadDemo.addEventListener('ready', (e) => {
    if (e.detail.name === 'bolt-typeahead') {
      setupEventHandlers();
    }
  });
}

In this example, we populate the Typeahead component with a small batch of results and customize the onSelected behavior to go directly to the result selected (vs the search results page) for exact matches.

Submitting the form with text that isn't a 1:1 match will fall back to the search results page (the behavior shown in the other demo).


{% include "@bolt-components-form/form.twig" with {
  children: include("@bolt-components-typeahead/typeahead.twig", {
    attributes: {
      class: [
        "js-typeahead-hook--exact-result"
      ]
    },
    max_results: 5,
  }),
  attributes: {
    action: "https://www.pega.com/search",
    target: "_blank",
    rel: "noopener",
    method: "GET"
  }
} %}

// NOTE: make sure you're running this code through a tool like Babel before shipping for cross browser compatibility!
const typeaheadDemo = document.querySelector(
  '.js-typeahead-hook--exact-result',
);

const typeaheadDemoItems = [
  {
    label: 'AI and improving the customer experience',
    description:
      '“Artificial intelligence” (AI) presents both distracting hype and powerful opportunities to drive customer engagement.',
    url: 'https://www.pega.com/ai-and-improving-customer-experience',
  },
  {
    label:
      'Gartner Magic Quadrant for Enterprise Low-Code Application Platforms 2019',
    description:
      'Pega was cited as a Visionary in Gartner’s new 2019 Magic Quadrant for Enterprise Low-Code Application Platforms.',
    url: 'https://www.pega.com/insights/resources/gartner-magic-quadrant-enterprise-low-code-application-platforms-2019',
  },
];

const setupEventHandlers = () => {
  typeaheadDemo.items = typeaheadDemoItems;

  typeaheadDemo.on('onSelected', (element, event, suggestion) => {
    const exactMatch = element.items.filter(
      (item) => item.label === suggestion.suggestionValue,
    )[0];

    function navigateTo(url) {
      if (window.location !== window.parent.location) {
        const win = window.open(url, '_blank', 'noopener');
        win.focus();
      } else {
        window.location = url;
      }
    }

    if (exactMatch && exactMatch.url) {
      if (exactMatch.url) {
        navigateTo(exactMatch.url);
      } else {
        navigateTo(`https://www.pega.com/search?q=${itemSelected.label}`);
      }
    } else if (suggestion.suggestionValue !== '') {
      navigateTo(`https://www.pega.com/search?q=${suggestion.suggestionValue}`);
    }
  });
};

if (typeaheadDemo) {
  if (typeaheadDemo._wasInitiallyRendered) {
    setupEventHandlers();
  }

  typeaheadDemo.addEventListener('ready', (e) => {
    if (e.detail.name === 'bolt-typeahead') {
      setupEventHandlers();
    }
  });
}

In this example, we populate the Typeahead component with a larger batch of results and customize the onSelected behavior to always go to the search results page when selecting an item.

Unlike the other demo, only perfect matches will allow you to submit (via the submit button) or select a result.

For example, manually selecting or entering Case Management in the input field will allow you to submit via hitting enter or clicking on the search icon. However, entering in Case Management2 instead would not submit.


{% include "@bolt-components-form/form.twig" with {
  children: include("@bolt-components-typeahead/typeahead.twig", {
    attributes: {
      class: [
        "js-typeahead-hook"
      ]
    },
    max_results: 5,
  }),
  attributes: {
    action: "https://www.pega.com/search",
    target: "_blank",
    rel: "noopener",
    method: "GET"
  }
} %}

// NOTE: make sure you're running this code through a tool like Babel before shipping for cross browser compatibility!
const typeahead = document.querySelector('.js-typeahead-hook');

const items = [
  {
    label: 'AI and improving the customer experience',
    description:
      '“Artificial intelligence” (AI) presents both distracting hype and powerful opportunities to drive customer engagement.',
    url: 'https://www.pega.com/ai-and-improving-customer-experience',
  },
  {
    label:
      'Gartner Magic Quadrant for Enterprise Low-Code Application Platforms 2019',
    description:
      'Pega was cited as a Visionary in Gartner’s new 2019 Magic Quadrant for Enterprise Low-Code Application Platforms.',
    url: 'https://www.pega.com/insights/resources/gartner-magic-quadrant-enterprise-low-code-application-platforms-2019',
  },
  {
    label: 'Pega Data & Integrations',
    description:
      "Take full advantage of integration opportunities with Pega's open architecture, allowing you to build applications faster and meet the increasing demands of your business.",
    url: 'https://www.pega.com/products/pega-platform/data-integrations',
  },
  {
    label: 'Digital Customer Experiences',
    description:
      'Deliver engaging digital customer experiences anywhere, anytime, with unique designs for your business right out of the box.',
    url: 'https://www.pega.com/products/pega-platform/digital-customer-experiences',
  },
  {
    label: 'DevOps and Testing',
    description:
      "Continuous integration and deployment. Continuous evolution. With one-click DevOps, you'll break barriers to delivery – and leapfrog competitors – by empowering business teams to…",
    url: 'https://www.pega.com/products/pega-platform/devops-testing',
  },
  {
    label: 'Pega Onboarding',
    description:
      'Intelligent work automation dramatically cuts time to revenue while ensuring compliance with global and local regulations, whether you are onboarding new clients, adding products…',
    url: 'https://www.pega.com/industries/financial-services/onboarding',
  },
  {
    label: 'Case Management',
    description:
      'Pega BPM and case management solutions allow you to build and manage enterprise-level strategic applications that can communicate with legacy systems.',
    url: 'https://www.pega.com/products/pega-platform/case-management',
  },
  {
    label: 'Pega Intelligent Virtual Assistant',
    description:
      "Across all channels, Pega's Intelligent Virtual Assistant engages users where they are and gives them experiences based on context, not just auto-responses.",
    url: 'https://www.pega.com/products/pega-platform/intelligent-virtual-assistant',
  },
];

const setupEventHandlers = () => {
  typeahead.items = items;
  typeahead.on('onSelected', (element, event, suggestion) => {
    const itemSelected = element.items.filter(
      (item) => item.label === suggestion.suggestionValue,
    )[0];

    if (itemSelected) {
      if (itemSelected.label) {
        if (window.location !== window.parent.location) {
          // const win = window.open(`${itemSelected.url}`, '_blank');
          const win = window.open(
            `https://www.pega.com/search?q=${itemSelected.label}`,
            '_blank',
            'noopener',
          );
          win.focus();
        } else {
          window.location = `https://www.pega.com/search?q=${itemSelected.label}`;
        }
      }
    }
  });
};

if (typeahead) {
  if (typeahead) {
    if (typeahead._wasInitiallyRendered) {
      setupEventHandlers();
    }

    typeahead.addEventListener('ready', (e) => {
      if (e.detail.name === 'bolt-typeahead') {
        setupEventHandlers();
      }
    });
  }
}