0

The autocomplete method successfully shows the String List of userNames but not adding it to the selected users. I tried and search a lot please help me any one.

xhtml file

...
...
            <div class="ui-sm-12 ui-md-2 ui-lg-2">
                <p:outputLabel  value="Users" />
            </div>
            <div class="ui-sm-12 ui-md-4 ui-lg-4">   
                <h:inputHidden value="#{service.usersListSize}" id="iTUsers" />

                <p:autoComplete id="usersid" widgetVar="userswVar" maxlength="60" minQueryLength="1"  
                                maxResults="10" styleClass="actCont" style="width: 100%;height:50px;"  
                                value="#{service.users}"
                                completeMethod="#{service.completeUserName}" var="u" unique="true"
                                itemLabel="#{u}" itemValue="#{u}" multiple="true"  forceSelection="true" disabled="#{service.disableFields}">
                    <p:ajax event="itemSelect"  listener="#{service.getListValues()}"  update="jbForm:tabview:iTUsers"/>

                </p:autoComplete>
            </div>
...
...

Service.java file

....
....

    private int usersListSize;
    private List<String> users = new ArrayList<>();

    public int getUsersListSize() {
        return usersListSize;
    }

    public void setUsersListSize(int usersListSize) {
        this.usersListSize = usersListSize;
    }

    public List<String> getUsers() {
        return users;
    }

    public void setUsers(List<String> users) {
        this.users = users;
    }

    public List<String> completeUerName(String query) {
        if (!query.startsWith("@")) {
            return new ArrayList<>();
        }
        String queryLowerCase = query.toLowerCase();
        List<String> uName = getListOfUsersName();

        return uName.stream().filter(t -> t.toLowerCase().contains(queryLowerCase)).collect(Collectors.toList());
    }

 
    public List<String> getListOfUsersName() {
        List<String> usersNamesList;
        usersNamesList.add("jhon");
        usersNamesList.add("jhonny");
        usersNamesList.add("Richard D'souza");
        usersNamesList.add("sheri'f");
        usersNamesList.add("ja'mes");
        List<String> userNameList = new ArrayList<>();
        for (String u : usersNamesList) {
            userNameList.add("@" + u);
        }
        return userNameList.stream().filter(t -> t.toLowerCase().contains("@")).collect(Collectors.toList());
    }

    public void getListValues() {
        setUsersListSize(this.users.size());
    }

    
    public void listUsers(Integer id) {
        users = retrieveUsersLst(id);
    }

    public List<String> retrieveUsersLst(Integer id) {

        List<String> ppList = new ArrayList<>();
        List<Users> userList = usersList(id);
        if (userList != null && !userList .isEmpty()) {
            int listSize = userList .size();
            String userName;
            for (int i = 0; i < listSize; i++) {
                userName = "@" + getUserName(userList .get(i).getId());
                ppList.add(userName);
            }
        }
        return ppList;
    }

  
    public List<Users> usersList(Integer id) {
        String queryString = "from Users where id=" + id;
        return dao.qryList(queryString, Dao.query.HQL);
    }

    public String getUserName(Integer uId) {
        String queryString = "select userName from Users where id=" + uId;
        return (String) dao.qryUniqueResult(queryString, Dao.query.HQL);
    }

It works fine except if user name contains any quotes Like this ' then the value is not selecting. I don't know why. please help me to resolve this issue. Thanks in advance. using prime faces 6.2.

1 Answers1

2

The problem is how the unique attribute of autocomplete is managed in PF 6.2. As you can see, from any browser developer tools, clicking on an item that contains the ' character, will generate an error, like this:

Uncaught Error: Syntax error, unrecognized expression: li[data-token-value='@Richard D'souza']

The error, in the components.js is:

PrimeFaces.widget.AutoComplete
...
h = PrimeFaces.escapeHTML(e.replace(/\"/g, '\''));
...
if (a.cfg.multiple) {
        var j = false;
        if (a.cfg.unique) {
          j = a.multiItemContainer.children('li[data-token-value=\'' + h + '\']').length != 0
    }

Note that if you type the entire string, there's no error and the item is added. This is already resolved in the newer PF version with:

 PrimeFaces.widget.AutoComplete
    ...
      var i = f.attr("data-item-value");
    ...
         if (a.cfg.multiple) {
             var h = false;
             if (a.cfg.unique) {
                 h = a.multiItemContainer.children("li[data-token-value='" + $.escapeSelector(i) + "']").length != 0
             }

As a solution you could:

  1. Upgrade PF, >= 7.0
  2. Remove the unique attribute, if your use case doesn't need it, or manage it at selection event (server-side)
  3. Override that function, in PF 6.2 adding escape logic
WoAiNii
  • 1,003
  • 1
  • 11
  • 19
  • Thank your very much for your help. Please can you suggest me any alternate way than changing this PF 6.2. – Mohammedsameer Inamdar Jul 05 '21 at 10:14
  • I think that the easy way is removing unique attribute and add the logic within getListValues function (if input is in selected list do not add, else add it). To override that binding function instead you could look at this [question](https://stackoverflow.com/questions/39639532/override-a-method-from-a-primefaces-specific-widget) – WoAiNii Jul 05 '21 at 11:52
  • Thanks a lot for your hep Your suggestion worked. – Mohammedsameer Inamdar Jul 06 '21 at 03:37