【问题标题】:Autocomplete unmatched results自动完成不匹配的结果
【发布时间】:2012-01-26 06:07:24
【问题描述】:

当我在 ice:selectInputText 中输入字符时,我正在尝试自动完成 我面临的问题是,当我输入字符时,它甚至会带来与我输入的字符不匹配的名称。 请参阅下面的屏幕截图以供参考。

理想情况下,自动完成应该只显示结果中的第一行,但它会显示与我输入的字符不匹配的行。

仅应显示 Abell Maryland 20606。

这是用于比较的代码,我如何修改它以适应我的要求,即只显示与我输入的内容匹配的结果。

public int compare(Object o1, Object o2) {
        if (o1 instanceof SelectItem) {
            s1 = ((SelectItem) o1).getLabel();
        } else {
            s1 = o1.toString();
        }

        if (o2 instanceof SelectItem) {
            s2 = ((SelectItem) o2).getLabel();
        } else {
            s2 = o2.toString();
        }            
        return s1.compareToIgnoreCase(s2);
    }
};

我正在学习 Icefaces 的本教程

http://wiki.icefaces.org/display/ICE/Auto-Complete

更新

我在 autocomplete.jspx 中的代码

 <ice:selectInputText rows="10" width="300"
                        listVar="emp"
                        valueChangeListener="#{mybean.updateList}"
                        listValue="#{mybean.list}">
                         <f:facet name="selectInputText">
                   <ice:panelGrid columns="3" columnClasses="empNameCol">
                         <ice:outputText value="#{emp.empName}"/>                         
                   </ice:panelGrid>

方法更新列表

public void updateList(ValueChangeEvent event) {

    setMatches(event);

    if (event.getComponent() instanceof SelectInputText) {
        SelectInputText autoComplete = (SelectInputText)event.getComponent();
        if (autoComplete.getSelectedItem() != null) {
            bean = (Bean)autoComplete.getSelectedItem().getValue();
        }            
        else {
            Bean tempCity = getMatch(autoComplete.getValue().toString());
            if (tempCity != null) {
                bean = tempCity;
            }
        }
    }
}

方法 setMatches

private void setMatches(ValueChangeEvent event) {

Object searchWord = event.getNewValue();
int maxMatches = ((SelectInputText)event.getComponent()).getRows();
List matchList = new ArrayList(maxMatches);

try {
    int insert = 
        Collections.binarySearch(dictionary, searchWord, AutoCompleteDictionary.LABEL_COMPARATOR);            
    if (insert < 0) {
        insert = Math.abs(insert) - 1;
    }

    for (int i = 0; i < maxMatches; i++) {                                
        if ((insert + i) >= dictionary.size() || i >= maxMatches) {
            break;
        }
        matchList.add(dictionary.get(insert + i));
    }
} catch (Throwable e) {
    e.printStackTrace();
    logger.error("Erorr finding autocomplete matches" + e.getMessage());
}        
if (this.matchesList != null) {
    this.matchesList.clear();
    this.matchesList = null;
}
this.matchesList = matchList;

}

更新 2

修改 setMatches 方法

 private void setMatches(ValueChangeEvent event) {
        Object searchWord = event.getNewValue();
        int maxMatches = ((SelectInputText) event.getComponent()).getRows();
        List matchList = new ArrayList(maxMatches);
         try {
             for(int i = 0; i < dictionary.size(); i++) {
                 SelectItem s = (SelectItem)dictionary.get(i);
                 if(s.getLabel().startsWith(searchWord.toString())) {
                     matchList.add(s);
                     if(matchList.size() == maxMatches)
                         break;
                 }   
             }
         } catch (Throwable e) {
             e.printStackTrace();
             logger.error("Erorr finding autocomplete matches" + e.getMessage());
         }        
         if (this.matchesList != null) {
             this.matchesList.clear();
             this.matchesList = null;
         }
         this.matchesList = matchList;
         }

【问题讨论】:

    标签: java jsf icefaces-1.8


    【解决方案1】:

    您必须更新 SelectItems 列表。您必须过滤列表(或创建一个仅包含匹配项的新列表),而不是仅仅对列表进行排序。下次自动完成列表呈现时,它将再次评估绑定列表。

    icefaces 的教程附有一些资源(底部)。看看AutoCompleteBean。方法updateList(ValueChangeEvent e) 调用setMatches(e)。在这个方法中,列表被分配了一个新的。

    // assign new matchList
    if (this.matchesList != null) {
       this.matchesList.clear();
       this.matchesList = null;
    }
    this.matchesList = matchList;
    

    这会导致 ui 组件仅显示与输入匹配的项目。

    总结一下ice:selectInputList 将始终显示其列表中包含的项目,因此减少列表中的项目以仅显示相关的项目。

    问候

    更新

    private void setMatches(ValueChangeEvent event) {
    Object searchWord = event.getNewValue();
    int maxMatches = ((SelectInputText)event.getComponent()).getRows();
    List matchList = new ArrayList(maxMatches);
    
    try {
        for(int i = 0; i < dictionary.size(); i++) {
            SelectItem s = dictionary.get(i);
            if(s.getLabel().startsWith(searchWord)) {
                matchList.add(s);
                if(matchList.size() == maxMatches)
                    break;
            }   
        }
    } catch (Throwable e) {
        e.printStackTrace();
        logger.error("Erorr finding autocomplete matches" + e.getMessage());
    }        
    if (this.matchesList != null) {
        this.matchesList.clear();
        this.matchesList = null;
    }
    this.matchesList = matchList;
    }
    
    // note: not optimized, just to explain how to do.
    

    更新 2(短版)

    /**
     * Fills the suggestionList with the given luceneResult.
     *
     * @param suggestionList                 The list to fill.
     * @param luceneResult                   The previously computed luceneResult.
     */
    private static void fillLookupSuggestionList(final List<SelectItem> suggestionList,
        LuceneResult luceneResult)
    {
        suggestionList.clear();
    
        String searchQuery = luceneResult.getLuceneResultConfig().getSearchQuery(); 
        if (luceneResult.getResultSize() <= 0)
        {
            suggestionList.add(new SelectItem(null, BundleHelper.i18n(LuceneLookupController.BUNDLE,
                LuceneLookupController.NO_ITEM_FOUND)));
        }
        else
        {
            List<LuceneResultEntry> results = luceneResult.getResult();
            for (LuceneResultEntry entry : results)
            {
                suggestionList.add(new SelectItem(entry.getMetaInfo(),
                    entry.getInfo().getDescription()));
            }
        }
    }
    

    【讨论】:

    • 我对此有疑问,我已经在更新列表中使用了这段代码。 // assign new matchList if (this.matchesList != null) { this.matchesList.clear(); this.matchesList = null; } this.matchesList = matchList; 那为什么我不能减少列表中包含的项目?很抱歉问这个问题,因为我不明白你的意思。
    • @Polappan 嗨。我也使用这个组件。每次用户输入内容时,我都会启动 Lucene 搜索,该搜索会返回结果。每次开始搜索时,我都必须创建一个新的 SelectItems 列表。这个临时列表分配给绑定到组件的 bean 成员。在这一点上,我很难理解您是如何减少列表项的。上面的代码仅显示排序。您能否提供一些代码来说明如何减少(和重新分配)?
    • 感谢您的帮助。我已将我的代码作为更新添加到我上面的原始帖子中。我的代码和教程代码几乎一样,只是数据来源不同。
    • @Polappan 好的,我们有了。这个例子不是最好的。二进制搜索仅查找给定 searchWord 的索引。之后,该示例使用从该索引开始的项目填充新列表,直到达到列表的最大值 - 如果它与输入匹配,则不会打扰。尝试类似上面更新的示例。问候
    • 再次感谢您的帮助。但是在修改 setMatches 方法后,我无法得到任何单词的任何结果。我已将上面的修改方法添加为更新 2。问候
    猜你喜欢
    • 2019-04-24
    • 1970-01-01
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-05
    • 1970-01-01
    • 2011-01-04
    相关资源
    最近更新 更多