Cookies help us deliver our services.

By using our services, you agree to our use of cookies. Learn more

I understand

The new 6.2 Liferay version has brought many changes and improvement, a few of these concerns AlloyUI modules that have changed or simply deprecated.

So let's see how to manage the autocomplete widget on Liferay 6.2, using Ajax loading.

For this example, we'll use data inside the classname table, only because it contains a sufficient number of test data.

The first, and most important, thing is the JSP page that will contain the widget and the script; then let's start with the definition of two input fields: the first to display the widget and the second to store the value to use in the portlet for saving:

<aui:input name="className" />
<aui:input name="valueToBeSaved" type="hidden" />

Then we'll define the URL and the datasource that will be used for the Ajax call to display the values in the widget; as it's an Ajax call that returns a JSON fragment, the URL will obviously be a resource one:

<liferay-portlet:resourceURL id="autocomplete" var="autocompleteURL" />

<aui:script use="autocomplete-list,datasource-io">
var datasource = new A.DataSource.IO({
	source: '<%=autocompleteURL%>'
});

...

The last part of the script is the most important which istantiates the widget:

var autoComplete = new A.AutoCompleteList({
	allowBrowserAutocomplete: false,
	activateFirstItem: true,
	inputNode: '#<portlet:namespace />className',
	maxResults: 10,
	on: {
		select: function(event) {
			var result = event.result.raw;
			A.one('#<portlet:namespace/>valueToBeSaved').val(result.classNameId);
} }, render: true, source: datasource, requestTemplate: '&<portlet:namespace />keywords={query}', resultListLocator: function (response) { var responseData = A.JSON.parse(response[0].responseText); return responseData.response; }, resultTextLocator: function (result) { return result.value; }, width: 400 }); </aui:script>

Please read the official AlloyUI documentation for more details on all the available parameters; however, we'll see the main ones:

allowBrowserAutocomplete
Disable the autocomplete feature of the browser
inputNode
This is the input field in which to write
on.select
This is the code to be run after the selection of a value; event.result.raw is the selected JSON object
source
This is the datasource for the Ajax call
requestTemplate
This is the list of parameters sent to the server for the search; the {query} placeholder contains the search query from the user
resultListLocator
This is the code to retrieve the values list from the Ajax call
resultTextLocator
This is the code to retrieve the value (of every single item) to be displayed in the list of values

The last part consists of the Java code that will handle the Ajax call for the search;​ nothing has changed compared to the old version of Liferay:

public void serveResource(ResourceRequest resourceRequest,
		ResourceResponse resourceResponse) throws IOException,
		PortletException {
	String resourceID = resourceRequest.getResourceID();

	if ("autocomplete".equals(resourceID)) {
		String keywords = ParamUtil.getString(resourceRequest, "keywords");

		JSONObject json = JSONFactoryUtil.createJSONObject();
		JSONArray results = JSONFactoryUtil.createJSONArray();
		json.put("response", results);

		try {
			DynamicQuery query = DynamicQueryFactoryUtil
					.forClass(ClassName.class);
			query.add(PropertyFactoryUtil.forName("value").like(
					StringPool.PERCENT + keywords + StringPool.PERCENT));
			List<ClassName> classNames = ClassNameLocalServiceUtil
					.dynamicQuery(query);

			for (ClassName className : classNames) {
				JSONObject object = JSONFactoryUtil.createJSONObject();
				object.put("classNameId", className.getClassNameId());
				object.put("value", className.getValue());
				results.put(object);
			}
		} catch (SystemException e) {
			e.printStackTrace();
		}

		writeJSON(resourceRequest, resourceResponse, json);
	} else {
		super.serveResource(resourceRequest, resourceResponse);
	}
}