Developing traditional Domino Web pages, I often used a symple techinque to dynamically change options in a combobox, depending on a key typed in an input box. Through an Ajax call to a Lotus Script agent, I could use HTML code sent back to the browser by the "print" statement to populate my "<select>" options.
Applying the same technique to XPages it's maybe possible, but it looked to me quite tricky and not consistent with the XPages model. Thus, I started playing with events and Server Side JavaScript to find out a different solution.
A combo box in a web page shows by default a list of options from a Notes View.
Typing a word or a sentence into the input box, a user can refine the search and get a subset of the original list shown in the combobox.
What I needed was not Type Ahead. A user must be able to type a word or a sentence and have the system automatically look for documents containing such a word anywhere in a couple of fields.
1. The database must be indexed
2. The input box is binded to a Request Scope "nameToSearch"
3. The "on blur" event for the input box and/or the "on click" event for the button have a simple Action (Server Side JavaScript) coded as follows:
"sessionScope.nameToSearch = requestScope.nameToSearch" and the Server Option put to "Partial update" --> combobox ID
4. Values for combobox are computed (dynamically), through a server side JavaScript
The code has been tested agains about 5.000 documents. Refining the choice list took less than a second.
1. create a new, indexed Database. If the database is not full text indexed, the code will not work
2. create a Notes form "Location". Add 4 text fields: "Name","City","State","CodePV"
3. create a Notes View "(Locations)". Write @SELECT Form="Location" as the Selection Formula. Then add 4 columns: "Name","City","State","CodePV"; the first one indexed.
4. create a Notes View "(FullLocations)". Here, you need just one column using the following formula: Name + " - city: " + City + " - state: " + State
Same selection formula as above.
5. Save several documents using the form you have just created. Fill in all fields for any saved document.
Those are just the elements you need to have the example working. Now, we'll start working on the XPages based code.
6. create a new custom control. Add to it an inputbox, a button and a combobox (call it "comboBox1")
7. select the inputbox, go to "Data" tab, select "Advanced" under "bind data using". In the Advanced box select Use=Scoped Variable, Parameter=Request scope,Variable name=nameToSearch, Compute dinamically.
8. Go to the Events tab, select the "on blur" event and add a Simple Action (Server)
9. In the dialog box, choose Category=Basic, Action=Execute script, Language=JavaScript (Server side)
10. Type a single line of code: sessionScope.nameToSearch=requestScope.nameToSearch
11. Then, go to the "Server Options" box and choose "Partial update". Hit the button "Select element..." and choose the "comboBox1" element.
12. Select the button, Label it "Search", and and add to it the same Action and Server Options as above.
13 Select the combobox element, go to the "Values" panel and hit "Add Formula item..."
14. Choose Language=JavaScript (Server Side), Condition=Compute dynamically, and add following code:
1. var criteria = sessionScope.nameToSearch;
2. var searchKey = "([Name] CONTAINS "+criteria+" OR [City] CONTAINS "+criteria+" OR [CodePV] CONTAINS "+criteria+")";
3. var currDoc:NotesDocument;
4. var myOpt=new Array();
5. if (null != criteria && criteria != ""){
6. var currDb:NotesDatabase = session.getCurrentDatabase();
7. var currView:NotesView = currDb.getView("(Locations)");
8. var viewElem = currView.FTSearch(searchKey);
9. if (viewElem >=1) {
10. for (i=1;i<=viewElem;i++) {
11. currDoc = currView.getNthDocument(i);
12. if (null != currDoc) {
13.
myOpt[i-1]=currDoc.getItemValueString("Name")+" - city:
"+currDoc.getItemValueString("City")+" - state:
"+currDoc.getItemValueString("State");
14. }
15. }
16. myOpt.sort();
17. }
18. else {
19. myOpt = "";
20. }
21. }
22. else {
23. myOpt = @DbColumn(@DbName(),"(FullLocations)",1);
24. myOpt.splice(0,0,"");
25. }
Lines 1-2 grab the text typed in the inputbox (stored in a sessionScope variable, see points 10 and 12 above) and build a string we will use later to perform the search.
For details on the search key syntax, look at the Domino 8 infocenter (http://publib.boulder.ibm.com/infocenter/domhelp/v8r0/index.jsp) and search for the "Refining a search query using operators" document.
Lines 6-8 instantiate the current database, and perform a FullText Search against the view "(Location)". Note that Database must be FullText Indexed, otherwise you'll get a runtime error on the web page.
A FullText Search performed on a NotesView returns an integer containing the number of documents in the view, corresponding to the search condition. Then, you can navigate the subset of documents in the view, using normal methods as .getFirstDocument, .getNextDocument, getNthDocument and so on.
Lines 9-20 just build an array scrolling selected documents in the view, and pass it as the choice list for our combobox. Line 16 sorts the array, since the "collection" of documents returned by the FTSearch method is not indexed.
If variable "criteria" is empty, lines 23-24 compute the value formula for our combobox using a traditional @DbColumn command, and adding a trailing empty value.
15. create a new XPage, name it whatever you want. I just called it "test"
16. add the custom control to the XPage
17. open the XPage in a browser and try it