This website uses cookies to ensure you get the best experience. Learn More.
Autocomplete avec Typeahead et Liferay
Sometimes you have to add an autocomplete module on your page to search contacts or other datas. If you want to use the very good Typeahead plugin in Liferay to have search suggestions in Ajax the solution is here. The ajax calls a resourceMapping on the controller to get the contacts in JSON format. In this resourceMapping function you can call whatever you want (Liferay service, LDAP, search engine…)
One thing is to manage with a local cache for not calling to many times the server when you change a letter.
<!—Typeahead javascript bundle-->
<script src="https://twitter.github.io/typeahead.js/releases/latest/typeahead.bundle.js"/>
<!—Liferay ressource URL for the ajax call-->
<portlet:resourceURL var="searchContactsURL" />
<input type="text" name="myInputSearch" id="myInputSearch"/>
<script type="text/javascript">
$(document).ready(function(){
// URL ajax de recherche, Input field of the search
autocompleteAjax ('${ searchContactsURL }', '#myInputSearch', 3);
autocompleteAjax ('${
searchContactsURL
}', '#myInputSearch
);
});
/**
* Autocomplete function using the "typeahead.js" plugin.
* @param ajaxURL, URL of the search: return JSON data
* @param inputField, input field to search datas
*/
function autocompleteAjax(ajaxURL, inputField, minLetters) {
var autocompleteName = "contacts";
// Cache for the results
var searchCache = [];
// To search again if we enter less than "minLetters" caracters: we have to clean the cache
$(inputField).keyup(function() {
if($(this).val().length < minLetters){
searchCache = [];
}
* Function to search if a search pattern is already in the cache.
var isInCache = function(pattern) {
var substrRegex = new RegExp(pattern, 'i');
var match = false;
$.each(searchCache, function(i, contact) {
if (substrRegex.test(contact.firstname)
|| substrRegex.test(contact.name)
|| substrRegex.test(contact.firstname + " " + contact.name)) {
match = true;
return match;
};
* Function to sort datas in the cache to keep only which matches with the search pattern.
var sortResults = function(pattern) {
var matches = [];
matches.push(contact);
return matches;
* Function to make an ajax call to search contacts. Only if the search pattern is not already in the cache.
var ajaxAutocompleteSearch = function() {
return function findMatches(searchPattern, comboBox) {
//to remove useless white space
searchPattern = $.trim(searchPattern).replace(/ {2,}/g,' ');
// If the search pattern is not in the cache make an ajax call to get the contacts
if (!isInCache(searchPattern)) {
$.ajax({
type : "POST",
async : false,
dataType : "json",
url : ajaxURL,
data : {
pattern : searchPattern
},
success : function(contacts) {
// To stock the results in the cache
searchCache = searchCache.concat(contacts);
comboBox(contacts);// To display the suggestions
} else {
// To sort suggestions of the cache
comboBox(sortResults(searchPattern));
// Initialisation of typeahead
$(inputField).typeahead(
{
hint : true,
highlight : true,
minLength : minLetters
name : autocompleteName,
displayKey : 'email',
templates : {
empty : [ '<div class="empty-message">', 'No contact found', '</div>' ].join('\n'),
suggestion : function(contact) {
return contact.firstname + " " + contact.name + " (" + contact.email + ")";
source : ajaxAutocompleteSearch()
</script>
import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion; … @ResourceMapping public void searchContacts(ResourceRequest request, ResourceResponse response, String pattern) throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(Inclusion.NON_NULL); List<Contact> listContacts = service.getContacts(pattern); mapper.writeValue(response.getWriter(), listContacts); response.getWriter().flush(); }
public class Contact { private String firstname; private String name; private String email; public Contact(String firstname, String name, String email) { this.nom = firstname; this.name = name; this.email = email; } public String getFirstname () { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }