-
Notifications
You must be signed in to change notification settings - Fork 37
HOW TO Create an auto complete field
An auto-complete field allows to propose values when the user entered data by suggesting the values matching the letters that have been entered so far.
It can be achieve easily in Plomino because Plomino uses JQueryUI (provided by collective.js.jqueryui).
First, you create a basic text field (in our example: department). To enable auto-completion in this field, we need to build a custom edit template where we will insert the needed JQueryUI javascript settings.
Go to your resources folder (Database design / Others / Resources folder), and add a new Page template named "department_autocomplete" with the following content:
<span>
<script>
$(function() {
$( "#department" ).autocomplete({
source: ["Development",
"Human resources",
"Marketing",
"Production",
"Purchasing",
"Sales"]
});
});
</script>
<input id="department" type="text" tal:attributes="name options/fieldname; value options/fieldvalue;" />
</span>
It is based on the regular Plomino TEXTFieldEdit template, but we have added a <script> tag to enable the auto-completion.
Now, you need to edit your department field, and enter the template name (department_autocomplete in our example) in the Field edit template parameter.
That's it.
In the first example, the department list is hard-coded in the field template.
But you might need to produce a value list dynamically. Let's imagine you want to enter the employee's manager name.
First, we create a regular text field named 'manager'.
But we also create a text computed for display field named 'employee_list' that will not be part of the form layout (you add it to the form using the "Add field link" in the left portlet or using the Plone Add menu, but you do not insert it in the form layout) with the following formula:
db = context.getParentDatabase()
other_employees = []
for doc in db.getView('allEmployees').getAllDocuments():
name = doc.employee_name
if name != context.employee_name:
other_employees.append(name)
return other_employees
It goes over all the employees, and it returns the list of the employee names but the name of the current employee (as we assume an employee cannot be managed by himself).
It could more complex of course (you might filter employees depending on their department for instance).
employee_list is a text field, but as you can see, its formula returns a list. Its type is actually not considered as we do not want to render it in a form, we just want to call its formula and get the result as JSON.
The URL to get the field value as JSON is the following one:
http://localhost:8090/Plone/how-to/auto-complete/frmEmployee/tojson?item=employee_list
It returns:
["Catherine", "Emmanuelle", "Eric", "Jean-Pierre"]
That is the list we want to provide to our autocomplete field, so we add a new Page template named "department_autocomplete" with the following content:
<span>
<script>
$(function() {
$.getJSON("tojson?item=employee_list", '', function(data){
$( "#manager" ).autocomplete({
source: data
});
});
});
</script>
<input id="manager" type="text" tal:attributes="name options/fieldname; value options/fieldvalue;" />
</span>
As usual with Javascript, function calls are nested: we use the JQuery getJSON function to call the JSON url, and when it succeeds, it instanciates the autocomplete feature using the data get from the JSON call.
Now, let's imagine we need to enter the city where the employee is located. We can use the Geonames.org JSON web service to get the list of existing cities which name starts with what the user has already entered.
Here is an example:
http://ws.geonames.org/searchJSON?featureCode=P&country=ES&name_startsWith=Bar
It returns all the cities (featureCode=P means you want cities) from Spain (country=ES) which name starts with the letters 'Bar'.
Here is the template to use:
<span><script>
$(function() {
$( "#city" ).autocomplete({
source: function(req, add){
$.getJSON("http://ws.geonames.org/searchJSON?maxRows=15&featureClass=P&country=ES&name_startsWith="+$("#city").val(), req,
function(data) {
var suggestions = [];
//read city names in results
data = data.geonames;
$.each(data, function(i, val){
suggestions.push(val.name);
});
//give values to add callback
add(suggestions);
}
);
}
});
});
</script><input id="city" type="text" tal:attributes="name options/fieldname; value options/fieldvalue;" /></span>
Compare to the manager auto-complete, we want to get a new list every time the user types a new letter, so the source is dynamic. So here the 'source' parameter is not a list of values but a function which calls the Geonames searchJSON service by passing the current value of the text field in the name_startsWith parameter. We have also restricted the number of values to 15 to avoid getting a useless long list.
Be careful, in those examples, we use the JQueryUI autocomplete feature, not the JQuery autocomplete plugin (not because it is not good, but just because JQueryUI autocomplete is part of collective.js.jqueryui which is a dependency of Plomino 1, whereas JQuery autocomplete plugin is not provided by the default).
This example will not work with Plomino 2 (where collective.js.jqueryui is not a dependency anymore).