Force selection of highlighted p:autoComplete item when panel is hidden by clicking outside

只愿长相守 提交于 2020-02-04 00:41:21

问题


I have a problem (bug?) with my auto-complete.

MyFaces 2.2.9 with PrimeFaces 5.1

This below is only an example to reproduce my error. I have a auto-complete - box in my modal dialog.

  1. Case 1 : I type something select "hello" from list in autocomplete and submit. Converter gets my person id and search the right person, all works fine.
  2. Case 2 (Error 1) : I type "h" and click in my modal area the h stays and list close. (When I submit my form h only disappears, no converter call) But I think h should disappear because force selection?
  3. Case 3 (Error 2) : The other error is harder. When I type "hello" (which is in the list) in my box and click in my modal dialog area, hello stays! When I submit the form I get "hello" in my converter and get back "null" because he only searches for the ids.

More for case 3: I try to explain it with more details (see comments): I type something in my autocomplete box, with a string, that is in my box.

than i click in my modal area. (NOT! directly on the choosable hello). Than the hello seems to be accept, too.

Now i click on my test button and in my converter public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) { is arg2 not the ID from hello, it is the string "hello". Only the string.

My expected behavior should be that there comes my id. The id comes only when i use the normal selection.

Hope you can help me. Thanks for your time :)

Question: Is this a bug or it is a misunderstanding from me?

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>

Converter:

@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;
    }
}

Controller:

@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;
    }
}

回答1:


This is not necessarily a bug in PrimeFaces, but likely an oversight in case forceSelection="true" is used. You'd somewhat expect the same behavior here as when you press the Tab key in the input.

You'd best report this as an issue to PF guys. In the meanwhile, here's how you can workaround it yourself, assuming PrimeFaces 5.1:

  1. Put a copy of raw source code of original autocomplete.js as /resources/primefaces/autocomplete/autocomplete.js in your webapp.

  2. Head to line 170. This is where the hide event of the autocomplete panel is being handled.

  3. At line 181, between the second and the third if block, insert the below code:

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

    This will force the highlighted item to be auto-selected when forceSelection="true" is used.

  4. Load the customized autocomplete.js in top of your <h:body> (not <h:head>!) as below:

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

This is indeed somewhat cumbersome, but as those functions are private, they can't be easily overridden from outside. Also attaching another listener won't work as it's explicitly doing a $.off() on any previous listeners.



来源:https://stackoverflow.com/questions/29474817/force-selection-of-highlighted-pautocomplete-item-when-panel-is-hidden-by-click

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!