Reputation: 49185
It seems Primefaces p:selectOneMenu
component wraps the rendered HTML <select>
tag in a div and shows the selected item as a different label. The changes made by the user are reflected to original <select>
by javascript I guess, resulting the onchange event binded to <select>
not to be worked. Thus my following binding of onchange event for all :input
s is not working for p:selectOneMenu
s.
function applyChangeHandler() {
$(':input').on('change', function() {
console.log('on change: ' + this.id);
});
}
However onchange attribute of p:selectOneMenu
is being fired. So Primefaces triggers this handler under the hood (again I guess).
<p:selectOneMenu id="myList" onchange="console.log('selectOneMenu')">
<f:selectItem itemLabel="val1" itemValue="val1"/>
<f:selectItem itemLabel="val2" itemValue="val2"/>
</p:selectOneMenu>
So my requirement is to somehow bind the onchange handler to all p:selectOneMenu
s from applyChangeHandler() function above. Or it may be triggerred manually with Primefaces specific API or other ways which I expect from you guys to share with. Otherwise a quick workaround will be to use h:selectOneMenu
instead.
My goal is to detect "unsaved changes on the page". So script above will be placed in a common template as:
<p:outputPanel id="sc" autoUpdate="true">
<script type="text/javascript">
applyChangeHandler();
</script>
</p:outputPanel>
Upvotes: 1
Views: 11410
Reputation: 2248
You need to add widgetVar to p:selectOneMenu to play with it in JS
<p:selectOneMenu id="myList" onchange="console.log('selectOneMenu')" widgetVar="myList">
<f:selectItem itemLabel="val1" itemValue="val1"/>
<f:selectItem itemLabel="val2" itemValue="val2"/>
</p:selectOneMenu>
this Will add this code to you page
$(function(){
PrimeFaces.cw("SelectOneMenu","myList",{
id:"A2:Form:myList",
effect:"fade"
})
});
Hope this will help.
Upvotes: 0
Reputation: 463
Instead of using onChange, you could utilize "DOMSubtreeModified".
This works for p:selectOneMenu
$(".ui-selectonemenu-label").each(function(index) {
$(this).on("DOMSubtreeModified", setDirty());
});
Also. Another possibility if you want the same generic code everywhere is to overwrite the prototype of SelectOneMenu as follows:
var origTriggerChange = PrimeFaces.widget.SelectOneMenu.prototype.triggerChange;
// if this code has been run already, don't accumulate triggerChangemethods!
if(origTriggerChange.isModified != "true"){
PrimeFaces.widget.SelectOneMenu.prototype.triggerChange = function(b){
this.jq.find("select").change();
origTriggerChange.call(this, b);
};
PrimeFaces.widget.SelectOneMenu.prototype.triggerChange.isModified = "true";
}
Upvotes: 0
Reputation: 4504
Why do you need to provide additional listeners when the framework has already provided you with such?
If your goal is to use jQuery you just put your handler in a js file accessible from the window global scope.
function myChangeHandler(that) {
//wrap the element with jQuery
var select = jQuery(that);
//Get the div parent. The actual wrapper of the `selection-menu` widget markup
var selectMenu = select.parents('div.ui-selectonemenu');
//From here I can manipulate any HTML child element using jQuery
jQuery('label.ui-selectonemenu-label', selectMenu).text('mooo');
}
Then call your handler onchange
, passing the selectOneMenu
as parameter
<p:selectOneMenu id="myList" onchange="myChangeHandler(this)">
<f:selectItem itemLabel="val1" itemValue="val1" />
<f:selectItem itemLabel="val2" itemValue="val2" />
</p:selectOneMenu>
Upvotes: 1