【问题标题】:Force selection of highlighted p:autoComplete item when panel is hidden by clicking outside通过单击外部隐藏面板时强制选择突出显示的 p:autoComplete 项目
【发布时间】:2015-06-11 01:26:15
【问题描述】:

我的自动完成有问题(错误?)。

MyFaces 2.2.9 和 PrimeFaces 5.1

以下只是重现我的错误的示例。我的模态对话框中有一个自动完成框。

  1. 案例 1:我输入了一些内容,从自动完成列表中选择“你好” 并提交。转换器获取我的个人 ID 并搜索合适的人, 一切正常。
  2. 案例 2(错误 1):我输入“h”并在我的模态区域中单击 h 停留并列出关闭。 (当我提交表单时,h 只会消失,没有 转换器调用)但我认为 h 应该消失,因为力 选择?
  3. 案例 3(错误 2):另一个错误更难。当我输入“你好” (在列表中)在我的框中,然后单击我的模态对话框区域, 你好留下!当我提交表单时,我的转换器中会出现“你好” 并返回“null”,因为他只搜索 id。

更多案例 3:我尝试用更多细节来解释它(参见 cmets): 我在我的自动完成框中输入了一些东西,带有一个字符串,就在我的框中。

比我点击我的模态区域。 (NOT!直接就choosable hello)。比你好似乎也可以接受。

现在我点击我的测试按钮,在我的转换器中public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) { 是 arg2 而不是来自 hello 的 ID,它是字符串“hello”。只有字符串。

我的预期行为应该是我的身份。只有当我使用正常选择时才会出现 id。

希望你能帮助我。 谢谢你的时间:)

问题:这是一个错误还是我的误解?

XHTML:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:p="http://primefaces.org/ui">

<h:head>
    <title>test</title>
</h:head>

<h:body>
    <h:form onkeypress="return event.keyCode != 13">
         <p:commandButton value="show Dialog" 
                          oncomplete="PF('dgl').show()"
                          update=":dglform"/>
    </h:form>

    <p:dialog widgetVar="dgl" modal="true" resizable="false">
         <h:form id="dglform" onkeypress="return event.keyCode != 13">
             <p:autoComplete id="auto"
                             forceSelection="true"
                             converter="personConverter"
                             value="#{myController.selectedPerson}"
                             var="per"
                             itemLabel="#{per.name}"
                             itemValue="#{per}"
                             completeMethod="#{myController.search}">
             </p:autoComplete>

             <p:commandButton value="test" update="@form" />
          </h:form>
      </p:dialog>
    </h:body>
</html>

转换器:

@FacesConverter("personConverter")
public class PersonConverter implements Converter{

    @Override
    public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {
        System.out.println(arg2);

        //Search my entity with id...
        return null;
    }

    @Override
    public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {
        if(arg2 instanceof Person){
            Person p = (Person) arg2;
            return String.valueOf(p.getId());
        }
        return null;
    }
}

控制器:

@ManagedBean
@ViewScoped
public final class MyController implements Serializable {

    private static final long serialVersionUID = 1L;
    private Person selectedPerson;
    private List<Person> persons;

    @PostConstruct
    public void init() {
        persons = new ArrayList<Person>();
        persons.add(new Person(1, "hello"));
        persons.add(new Person(2, "hello2"));
    }

    public void selectListener(SelectEvent event){
        System.out.println("SELECT!");
    }

    public Person getSelectedPerson() {
        return selectedPerson;
    }

    public void setSelectedPerson(Person selectedPerson) {
        this.selectedPerson = selectedPerson;
    }

    public List<Person> search(String qry) {
        return persons;
    }
}

【问题讨论】:

  • 我没有看到任何可能被称为“unexpected”或“bug”的东西。您列出的所有这三种情况都可以正常工作。现在的问题是什么? 1) “我输入一些东西,从自动完成列表中选择“你好”并提交。转换器获取我的人员 ID 并搜索合适的人员,一切正常。” - 没什么好说的。 2)“但我认为 h 应该因为强制选择而消失?” - 。 3)“当我提交表单时,我在转换器中得到“hello”并返回“null”,因为他只搜索 id。” - 这与自动完成无关全部。待续。
  • 这完全取决于您如何使用标量值(字符串到对象的转换)在getAsObject() 中构造Person 的实例,并由getAsString()(对象到字符串的转换)返回转身,当你显示。
  • 我认为存在误解 ;) ...案例 2 和 3 的工作方式与预期不同。案例 2:当我点击我的模态区域时,h 不会消失,当我点击它工作的表单时,它会保持不变。案例 3:当键入自动完成框中的单词并单击模态区域时,该单词将保留并在我的转换器中提供与 case1 不同的字符串。当我直接在我的盒子里选择东西时。
  • 我确实得到了所描述的行为。对于#2,您应该添加required="true" requiredMessage="Please select existing person" 左右以使其更直观。对于#3,我不确定您的意图是什么,因为您明确表示您的转换器返回 null,但不清楚它是否只是为了演示或您的实际问题而省略“不相关”代码的一部分(但是你为什么在问题中明确说明这一点?)
  • 知道了。我重现了你的问题。这确实是与&lt;p:autoComplete&gt; 关联的JavaScript 中的一个错误。我还没有检查它的 JS,但我的印象是实际值仅在单击事件期间设置,而不是在模糊事件期间设置,因此修复将相当简单:在模糊事件上也附加相同的侦听器,或者至少到菜单的隐藏事件,如果有的话。

标签: javascript jsf primefaces autocomplete


【解决方案1】:

这不一定是 PrimeFaces 中的错误,但可能是使用 forceSelection="true" 时的疏忽。您可能会期望这里的行为与您在输入中按 Tab 键时的行为相同。

您最好将此作为issue 报告给 PF 家伙。同时,假设 PrimeFaces 5.1,您可以自己解决此问题:

  1. 将原始autocomplete.jsraw source code 副本作为/resources/primefaces/autocomplete/autocomplete.js 放入您的Web 应用程序中。

  2. 前往line 170。这是处理自动完成面板的隐藏事件的地方。

  3. 在第 181 行,在第二个和第三个 if 块之间,插入以下代码:

    if ($this.cfg.forceSelection) {
        $this.items.filter('.ui-state-highlight').click();
    }
    

    这将强制在使用forceSelection="true" 时自动选择突出显示的项目。

  4. 将自定义的autocomplete.js 加载到您的&lt;h:body&gt; 顶部(不是&lt;h:head&gt;!),如下所示:

    <h:outputScript library="primefaces" name="autocomplete/autocomplete.js" target="head" />
    

这确实有点麻烦,但由于这些函数是私有的,它们不能轻易地从外部覆盖。附加另一个侦听器也不起作用,因为它明确地对任何以前的侦听器执行$.off()

【讨论】:

    猜你喜欢
    • 2010-11-18
    • 2013-04-18
    • 1970-01-01
    • 1970-01-01
    • 2012-05-06
    • 1970-01-01
    • 2017-06-30
    • 2012-09-20
    • 1970-01-01
    相关资源
    最近更新 更多