jqueryajaxprimefacesjquery-eventsselectonemenu

Primefaces selectOneMenu ajax event on select / click


I am using Primefaces 5.0. I have a selectOneMenu with ajax listener inside:

<p:selectOneMenu value="#{mybean.myselection}" >
    <f:selectItems value="#{mybean.mylist}" />
    <p:ajax listener="#{mybean.test}" />
</p:selectOneMenu>

The listener is called every time when value is changed. This works fine. But I also need an event like "select" or "click" which fires an action also when the selecteditem is clicked.

I could not find an event in PF UserGuide. Is there an easy way to do this?

EDIT: Add Javascript functioN.

   <h:form>
    <p:selectOneMenu value="#{mybean.myselection}" widgetVar="mySelect">
        <f:selectItems value="#{mybean.mylist}" />
        <p:ajax listener="#{mybean.test}" />
    </p:selectOneMenu>
   <h:form>

<script>
            //<![CDATA[
            $(document)
                    .ready(
                            function() {
                                PF('mySelect').selectItem = function(item,
                                        silent) {
                                    var selectedOption = this.options.eq(this
                                            .resolveItemIndex(item)), currentOption = this.options
                                            .filter(':selected'), shouldChange = null;

                                    if (this.cfg.editable) {
                                        shouldChange = (selectedOption.text() != this.label
                                                .val());
                                    } else {
                                        shouldChange = true;
                                    }

                                    if (shouldChange) {
                                        this.highlightItem(item);
                                        this.input.val(selectedOption.val())

                                        this.triggerChange();

                                        if (this.cfg.editable) {
                                            this.customInput = false;
                                        }
                                    }

                                    if (!silent) {
                                        this.focusInput.focus();
                                    }

                                    if (this.panel.is(':visible')) {
                                        this.hide();
                                    }
                                }
                            })
            //]]>
        </script>

Solution

  • In the selectItem function of the selectOneMenu widget you can see that when the item is selected a condition is present which is sameOption, if it's true the change event won't be triggered.

    So this is by design. To override this you have multiple options, you can alter the prototype of the selectItem, where the sameOption is considered always false, meaning you don't have to delete all the code related to that option just for simplicity of going backwards, or you can take out that option for ever!

    This example is where I toke that option from the equation...

    PrimeFaces.widget.SelectOneMenu.prototype.selectItem = function(item, silent) {
        var selectedOption = this.options.eq(this.resolveItemIndex(item)),
        //sameOption = selectedOption.val() == currentOption.val() | or make it false |
        currentOption = this.options.filter(':selected'),
        shouldChange = null;
    
        if(this.cfg.editable) {
            shouldChange = (selectedOption.text() != this.label.val()); //changes done here, see original function 
        }
        else {
            shouldChange = true;
        }
    
        if(shouldChange) {
            this.highlightItem(item);
            this.input.val(selectedOption.val())
    
            this.triggerChange();
    
            if(this.cfg.editable) {
                this.customInput = false;
            }
        }
    
        if(!silent) {
            this.focusInput.focus();
        }
    
        if(this.panel.is(':visible')) {
            this.hide();
        }
    }
    

    Now altering the prototype of the whole object might not be your case, if you want this behaviour for specific selectOneMenu you may change only the function like this:

    PF('selectOneMenuWidgetVarName').selectItem = function(item, silent) {
        var selectedOption = this.options.eq(this.resolveItemIndex(item)),
        currentOption = this.options.filter(':selected'),
        shouldChange = null;
    
        if(this.cfg.editable) {
            shouldChange = (selectedOption.text() != this.label.val());
        }
        else {
            shouldChange = true;
        }
    
        if(shouldChange) {
            this.highlightItem(item);
            this.input.val(selectedOption.val())
    
            this.triggerChange();
    
            if(this.cfg.editable) {
                this.customInput = false;
            }
        }
    
        if(!silent) {
            this.focusInput.focus();
        }
    
        if(this.panel.is(':visible')) {
            this.hide();
        }
    }
    

    That way the change event will be triggered even if the same value is selected. You need to execute this code in the $(document).ready.