The other day I found an occasion to make a more sophisticated use of GWT's
and after selection, values should be inserted like that
Although the basic idea of doing so was thought of by Google's engineers, there is no clear path given to ultimately get it done. I found a working example of how to achieve something similar over at the PermGen error blog. Kudos to the author over there - he certainly got me kickstarted. However, I found it awkward to manage the text matching "myself", especially as I liked the feature set of the
SuggestBox
. Not only did I intend to use the "suggestion feature" based on a POJO's attribute, I also wanted to- fill more widgets with other attribute values of the POJO the suggestion was based on
- present the data of the other attributes by showing them to the user beforehand; ideally as part of the suggestion itself
and after selection, values should be inserted like that
Although the basic idea of doing so was thought of by Google's engineers, there is no clear path given to ultimately get it done. I found a working example of how to achieve something similar over at the PermGen error blog. Kudos to the author over there - he certainly got me kickstarted. However, I found it awkward to manage the text matching "myself", especially as I liked the feature set of the
MultiWordSuggestOracle
(and wanted to offer the user the possibility to match the brand also); so I looked for a way to extend the latter.
Define our own Suggestion
We start easy by following the recommendation to implement our own Suggestion
class:public class ArticleSuggestion extends MultiWordSuggestion { private final Article article; public ArticleSuggestion(Article article, String displayString) { super(article.getName(), displayString); this.article = article; } public Article getArticle() { return this.article; } }
Extending MultiWordSuggestOracle
This one's a bit tricky. Unfortunately, there are no hooks or plugin-points in that class with which to easily provide your own logic. Also, basically all of the text matching (the reason that made me want to extend it) is defined in private methods. So I ended up with a somewhat blunt approach - which obviously works for me, and I assume works for most scenarios as well.public class ArticleSuggestOracle extends MultiWordSuggestOracle { private final MapsuggestionMap = new HashMap (); public void add(Article article) { String suggestion = article.toSuggestion(); this.suggestionMap.put(suggestion, article); super.add(suggestion); } public void requestSuggestions(Request request, final Callback callback) { super.requestSuggestions(request, new Callback() { @Override public void onSuggestionsReady(Request request, Response response) { callback.onSuggestionsReady(request, modifyResponse(response)); } }); } private Response modifyResponse(Response response) { ArrayList articleSuggestions = new ArrayList (); for (Suggestion originalSuggestion : response.getSuggestions()) { MultiWordSuggestion suggestion = (MultiWordSuggestion) originalSuggestion; Article article = this.suggestionMap.get(suggestion.getReplacementString()); articleSuggestions.add(new ArticleSuggestion(article, suggestion.getDisplayString())); } response.setSuggestions(articleSuggestions); return response; } }
Reacting on a selected suggestion
Now, set up aSuggestBox
using the ArticleSuggestOracle
, and assign a SelectionHandler
just like that:
articleSuggestBox.addSelectionHandler(new SelectionHandlerThe power of the() { @Override public void onSelection(SelectionEvent event) { ArticleSuggestion suggestion = (ArticleSuggestion) event.getSelectedItem(); Article suggestedArticle = suggestion.getArticle(); handleSuggestedArticle(suggestedArticle); } });
MultiWordSuggestOracle
awaits you!