Syntax question on using FTSearch results as Type Ahead choices

I’m using type ahead to give users a choice to pick a part number. All parts are stored in a separate db. They can use a radio field to choose to either search By Part Number or By Description. If they choose By Part Number, I simply use @DbLookup on a view column with [PartialMatch] and return the results. This works fine.

If they choose By Description, then I get a dcol with db.FTSearch, loop thru the results to create a string of choices, and then split the results to return an array. This does not work.

I used print statements in the loop to verify that I’m getting results, and I am. Since returning an array did not work, I also tried leaving the list of choices in a string, and set the Type Ahead delimiter property to ~, but that didn’t work either.

In help, it looks like split returns a string, so I tried using @Explode instead - that didn’t work either.

What do I have to do to return a list of choices from a string for Type Ahead?

(in simpler terms, how do I return “one,two,three” as Type Ahead choices)

Bob

Subject: Add a view by Description?

Why not add a hidden view whose first column is sorted by Description and include this column in a @DbLookup formula? If the description is very long you could have the column include only the first N characters.

Subject: That would work for “starts with” searches, but…

FTSearch performs a “floating search” which is really what I need for the Description field. That’s why I can’t just use a sorted column of Descriptions.

For Part Numbers, users know the first few characters, but for Descriptions, they won’t necessarily know what it starts with, just that it contains the text HEAT or something.

Subject: split and typeahead choices

I assume this is an xpages web application since you are mixing formula and API functions so freely.

Perhaps if you showed your code someone could suggest something.

Subject: Here’s the Type Ahead code

var partdbpath = sessionScope.currentPartDBPath;var option = getComponent(“PartSearchOpt”).getValue();

var searchstr = getComponent(“SelPart”).getValue();

var db = new Array(@Subset(@DbName(),1), partdbpath);

var vname = “”;

if (option==“ItNbr”){

vname = "wPartsbyNumber";

var list = @DbLookup(db, vname, searchstr,1,"[PARTIALMATCH]");

return(list);

}

else if (option==“EngNo”) {

vname = "wPartsbyEngNumber";

var list = @DbLookup(db, vname, searchstr,1,"[PARTIALMATCH]");

return(list);

}

else {

var reslist = "";

var tmpstr = "";

var partdb:NotesDatabase = getDbCurrentFolder("part_mka.nsf");

if (partdb==null){

	print("partdb is null");

	return("");

}

var dcol = partdb.FTSearch(searchstr);

if (dcol.getCount()==0) {

	print("dcol.count=0 for " + searchstr);

	return("");

}

else if (dcol.getCount()>5000) {

	print("dcol.count>5000 for " + searchstr);

	return("");

}

var doc = dcol.getFirstDocument();

while (doc != null) {

	tmpstr = doc.getItemValueString("ItNbr") + " - " + doc.getItemValueString("ItDsc");

	if (doc.getItemValueString("EngNo")!=null && doc.getItemValueString("EngNo")!=""){

		tmpstr = tmpstr + ", Eng No.: " + doc.getItemValueString("EngNo");

	}

	if (reslist==""){

		reslist = tmpstr;

	}

	else {

		reslist = reslist + "~" + tmpstr;

	}

	doc = dcol.getNextDocument();

}

var listarr = @Explode(reslist,"~");

return(listarr);

var results = listarr.sort();

return(results);

Subject: Discovered the solution - here it is

The answer to my question is that when computing the values yourself, you have to return an unordered list as the result set.

See this blog: XPages Development: Extending the XPages Type Ahead Functionality

So, here’s my code that works for what I was after:

//set minimum chars to 3 to minimize choices

//uses normal type ahead for item number and eng number

//uses full text search for description searches

var partdbpath = sessionScope.currentPartDBPath;

var option = getComponent(“PartSearchOpt”).getValue();

var searchstr = getComponent(“SelPart”).getValue();

var db = new Array(@Subset(@DbName(),1), partdbpath);

var vname = “”;

if (option==“ItNbr”){

vname = "wPartsbyNumber";

var list = @DbLookup(db, vname, searchstr,1,"[PARTIALMATCH]");

var reslist = @Explode(@Implode(list,"~"),"~");

}

else if (option==“EngNo”) {

vname = "wPartsbyEngNumber";

var list = @DbLookup(db, vname, searchstr,1,"[PARTIALMATCH]");

var reslist = @Explode(@Implode(list,"~"),"~");

}

else {

var reslist = new Array();

var tmpstr = "";

var partdb:NotesDatabase = getDbCurrentFolder("part_mka.nsf");

if (partdb==null){

	print("partdb is null");

	return("");

}

var dcol = partdb.FTSearch(searchstr);

if (dcol.getCount()==0) {

	print("dcol.count=0 for " + searchstr);

	return("");

}

else if (dcol.getCount()>5000) {

	print("dcol.count>5000 for " + searchstr);

	return("");

}

var doc = dcol.getFirstDocument();

while (doc != null) {

	tmpstr = doc.getItemValueString("ItNbr") + " - " + doc.getItemValueString("ItDsc");

	if (doc.getItemValueString("EngNo")!=null && doc.getItemValueString("EngNo")!=""){

		tmpstr = tmpstr + ", Eng No.: " + doc.getItemValueString("EngNo");

	}

	reslist.push(tmpstr);

	doc = dcol.getNextDocument();

}

}

//return value must be an unordered list

var result = “

    ”;

    for (i=0; i<reslist.length; i++) {

    result += '<li><span class="informal"></span>' 
    
    + reslist[i] 
    
    + '<span class="informal"></p></span></li>'; 
    
    }
    

    return result + “

”;