SelectOneMenu resets and fires change event on ALT press

1.7k views Asked by At

Using PF 5.1, JSF 2.2.7 on Glassfish 4.1.

I have this simple example with a selectOneMenu:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://xmlns.jcp.org/jsf/html"
  xmlns:p="http://primefaces.org/ui"
  xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
  xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
    <title>Test</title>
</h:head>
<h:body>
    <h:form>

        <p:selectOneMenu value="#{testBean.text}">
            <p:ajax listener="#{testBean.test()}" update="outputpanel"/>
            <f:selectItem itemLabel="1" itemValue="1"/>
            <f:selectItem itemLabel="2" itemValue="2"/>  
            <f:selectItem itemLabel="3" itemValue="3"/> 
        </p:selectOneMenu>

        <p:outputPanel id="outputpanel"> 
            #{testBean.text}
        </p:outputPanel>

    </h:form>
</h:body>
</html>

Bean:

import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;

@Named
@ViewScoped
public class TestBean implements Serializable
{
private String text;

public String getText() {
    return text;
}

public void setText(String text) {
    System.out.println("settext: " + text);
    this.text = text;
}

public void test() {
    System.out.println("test called");
}

}

It works as expected, except that if the dropdown has focus and I press ALT on windows or CMD on mac it will call the listener and also reset the dropdown. This happens when the dropdown is not at its default value (when its already on 2 or 3). And this means I cannot for example press ALT + TAB to check something in another open program - when I come back it will be reset.

Why this wicked behaviour and how to avoid it? I would rather not have a press on ALT to fire an event="change" and reset the component.

3

There are 3 answers

1
BalusC On BEST ANSWER

This is a bug in the JavaScript associated with <p:selectOneMenu>. It's not distinguishing control keys (Alt, Ctrl, etc) from character keys (A, B, 1, 2, etc) when filtering menu items via keyboard.

Basically, in the PrimeFaces.widget.SelectOneMenu object definition in primefaces.js file, the on("keyup.ui-selectonemenu", function...) has to be replaced by .on("keypress.ui-selectonemenu", function...). The keypress event is only triggered when a character key is pressed. This way the whole switch check can also be removed.

  1. Get a copy of /javax.faces.resource/primefaces.js.xhtml?ln=primefaces and save it as /resources/primefaces/primefaces.js in your webapp. Resources in WAR have higher loading precedence than those in JAR.

  2. Ctrl+F on keyup.ui-selectonemenu and replace this by keypress.ui-selectonemenu.

  3. Save.

  4. Profit.

In the meanwhile, report this issue to PrimeFaces guys, so that they can fix it properly on their side. Once the fix is released, you can remove the customized script.

1
Srikanth On

Thankq very much BaluC

Small advise: i'm working with primefaces 5.2 and above issue is simulating in only firfox, remaining IE and chrome working fine. So i modified js code like below

(window.navigator.userAgent.indexOf("Firefox")>0) ? "keyup.ui-selectonemenu" : "keypress.ui-selectonemenu"

as you said, i given for escape key handle and filter is working fine when we give filter="true". But with out giving filter="true", when focus on selectonemenu then if we click one key (character) then relevent value will focus. example: if click 's' then 's' started word will focus. This feature is not working

0
Ludovic Bonivento On

I've only a comment about BalusC good answer. I get same problem and this solution solve it.

First thanks a lot BalusC !

But pay attention do not change 'keyup' to 'keypress' for filter line below :

this.filterInput.on("keyup.ui-selectonemenu",function(...

Only for escape key handle :

c.ESCAPE:a.handleEscapeKey(d);break}}).on("keypress.ui-selectonemenu"

Otherwise you will have problems with the filter will not work properly. For example first char entered will not filter the list.

Thanks to all