Customizing the Suggestions Dropdown in Search Bar Widget

The Challenge

The Search Bar widget is equipped with an autocomplete functionality that is capable of providing standard suggestions and suggestions that work with search blueprints. Currently, this feature works on the default Search Bar component that is rendered with React, but there is no version available for the widget template. The Search team has received several requests from developers to offer options to customize the Search Bar and dropdown suggestions.

This blog will demonstrate an existing solution, and propose a potential enhancement to Liferay to make templating the search bar with suggestions easier. If you develop widget templates in Liferay, we'd love to hear if you'd appreciate the proposed enhancement.

 

Idea #1 - Applying jQuery into Search Bar Display Templates

Template with CSS + Devbridge’s jQuery Autocomplete

You can create a Widget Template using Ajax Autocomplete for jQuery from Devbridge, CSS and template code to display suggestions grouped by type.

Example Templates with jQuery

A simple implementation that renders suggestions is possible with jQuery, here are a few examples with images:

SearchBar with Suggestions

SearchBar with Suggestions (Categories)

 

Benefits of using these jQuery templates:

  • jQuery is well known, has documentation, and is straightforward to add onto the script. There was some documentation about being able to categorize the items within autocomplete on the jQuery website here, which was helpful in listing names for each suggestion group: Autocomplete

  • This is all copy paste into template editor and does not require any additional deployment.

Challenges of using these jQuery templates:

  • Forming HTML is a bit complicated. The code would append the divs and links to the menu, and getting the right html would look like this: '<a class="dropdown-item" href="' + item.attributes.assetURL + '">'. Simple changes would require some trial and error to render correctly, and the results could get hard to read.

  • There may be uncertainties with using the jQuery-Autocomplete from Devbridge (who is responsible for its continued support, how would possible bugs be addressed).

  • Some information is necessary to properly render suggestions and is not conveniently known, like using conditionals to find the proper search scope and applying the suggestions contributor configuration into the fetch call.

 

 

Idea #2 - Creation of a JS Utility Liferay.Search.Autocomplete

In order to offer better customization of the autocomplete dropdown, Liferay could provide a Liferay.Search.Autocomplete JavaScript utility inside the search bar template.

GitHub Branch with POC: https://github.com/oliv-yu/liferay-portal/tree/LPD-22537-autocomplete-utility

With this utility, you could paste in these lines at the end of the FreeMarker template, adding listeners onto the search input and rendering a dropdown based on the typed input:

<#if searchBarPortletDisplayContext.isSuggestionsEnabled()>
	<script>
		Liferay.on('liferaySearchAutocompleteReady', () => {
			Liferay.Search.Autocomplete('${searchInputId}', {
				containerClass: 'search-bar-autocomplete',
				destinationFriendlyURL:
					'${searchBarPortletDisplayContext.getDestinationFriendlyURL()}',
				scopeIfDefined:
					'${searchBarPortletDisplayContext.getScopeIfDefined()}',
				showEmptyResultsMenu: true,
				suggestionsContributorConfiguration:
					'${searchBarPortletDisplayContext.getSuggestionsContributorConfiguration()}',
				suggestionsURL:
					'${searchBarPortletDisplayContext.getSuggestionsURL()}',
				templates: {}
			});
		});
	</script>
</#if>

And with that added, an autocomplete dropdown would be attached to the search input upon typing!

Parameters of Liferay.Search.Autocomplete

Name

Type

Description

searchInputId

string

Value of id of the search bar input that identifies where to attach the event listener and append an autocomplete dropdown

containerClass

string

Classname that would be applied to the dropdown

showEmptyResultsMenu

string

Value to determine whether or not a dropdown would appear when performing a search with no results

destinationFriendlyURL, scopeIfDefined, suggestionsContributorConfiguration, suggestionsURL

string

Parameters required to fetch suggestions and are available within the searchBarPortletDisplayContext

templates

object

Contains the different functions for rendering parts of the dropdown. Each function has a default and can be overridden:

  • renderEmptyResultsMenu

  • renderHeader

  • renderItem

  • renderMenu

  • renderShowMore

Example with More Customization

In order to vary the layout of the dropdown, you could add render* functions inside templates that override the default. Here is an example:

Sample Template with custom searchbar dropdown of two columns and linked labels

 

Benefits of using the proposed JS utility:

  • Gives developers the flexibility to add their own layer of changes to the dropdown, from simple edits to more complex functionality like processing the input text and outputting a specialized link.

  • Liferay developers would not need to know the setup involved in making complicated suggestion calls, like setting up conditionals to determine scope and applying the suggestions contributor configuration. They would just need to pass parameters into the utility.

  • This utility would not require additional dependencies, and it is written in plain Javascript.

Challenges of using the proposed JS Utility:

  • Forming HTML can still be complicated, as mentioned in the first idea. Writing lines such as `<a href="` + hit.attributes.assetURL + `">` could be difficult to read and maintain. It might be important to include a sample template to make it easier for anyone to start developing.

 

Here you've seen one existing solution to templating the Search Bar widget while providing search suggestions, and a proposal to make this customization easier. Please feel free to share any thoughts - questions, examples, improvements - about both these topics. Thank you for reading!