API

AUI Autocomplete with service builder json datasource

Since it’s not so trivial to correctly understand AlloyUI Autocomplete that’s shipped with Liferay 6.2 then here’s an example on how to make an autocomplete that uses a custom service builder json web service as a datasource.
We will use AUI Autocomplete widget and then user Liferay Service library to fetch the result from our own custom service builder built JSON web service.

This is the look we are trying to achive:
aui autocomplete service builder

Full portlet view.jsp code:


<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@ taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme" %>
<%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui"%>
<%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %>

<portlet:defineObjects/>
<liferay-theme:defineObjects />

<aui:input name="contactName" type="text" />

<aui:script use="autocomplete-list,aui-base,aui-io-request-deprecated,autocomplete-filters,autocomplete-highlighters,datasource,datasource-get,datatable-datasource">

// Please note that this contact portlet service is a service builder generated JSON web service.
// We pass the groupId as a query param because our service expects it. Liferay has a nice javascript method for finding the group id.
var contactSearchDS = new A.DataSource.IO({source: '/api/jsonws/contact-portlet.contact/get-contacts-by-name?groupId='+Liferay.ThemeDisplay.getScopeGroupId()});

var contactSearchQueryTemplate = function(query) {
        // Here's an example on how to pass additional parameters to the query for you service
        // In our case we are fetching only the first 20 items and specify the ordering by name
	var output = '&name='+query.trim()+'&sort=name&dir=asc&start=0&end=20';
	return output;
}

var contactSearchLocator = function (response) {
	var responseData = A.JSON.parse(response[0].responseText);
// For debugging you can do: console.debug(responseData);
    return responseData;
};

var contactSearchFormatter = function (query, results) {
	return A.Array.map(results, function (result) {
// For debugging: console.debug(result.raw);
		return '<strong>'+result.raw.fullName+'</strong><br/>'+result.raw.mobile+' '+result.raw.phone+' '+result.raw.email;
	});
};

var contactSearchTextLocator = function (result) {
// This is what we place in the input once the user selects an item from the autocomplete list.
// In our case we want to put contact full name in there.
	return result.row.fullName;
};

var contactSearchInput = new A.AutoCompleteList({
	allowBrowserAutocomplete: 'false',
	resultHighlighter: 'phraseMatch',
	activateFirstItem: 'false',
	inputNode: '#<portlet:namespace/>contactName',
	render: 'true',
	source: contactSearchDS,
	requestTemplate: contactSearchQueryTemplate,
	resultListLocator: contactSearchLocator,
        resultFormatter: contactSearchFormatter,
	resultTextLocator: contactSearchTextLocator		
});

</aui:script>		

We’ll post an example of “multi-autocomplete” input also soon. That one requires a lot more code but allows selecting multiple contacts and shows them as “tags” above the input box. Much like the facebook name finder works.

As always, if you have questions or suggestions then please comment below.