f:ajax don't fired with event "change" - ajax

The code:
<h:inputText id="date" value="#{holidayRequestController.dates}">
<f:ajax execute="date" event="change"
listener="#{holidayRequestController.generateDates}"
render="generateDate" />
</h:inputText>
<h:panelGroup id="generateDate" class="span8"> ..</h:panelGroup>
With this code when i using date picker to select a date in from h:inputText, and f:ajax will fire event and populate this date to generateDate component.
But when i change to multiDatePicker, f:ajax don't fired with event "change"(although it work with event "blur", but i have some problem to use "blur").
What should i do to use event "change" for multiDatePicker?
One other question: is there support f:ajax for tag h:inputHidden in jsf?
Thanks for support

That can happen if the change event is actually not fired. That can in turn happen if the input element's value is only manipulated via JavaScript and not via enduser interaction.
Basically, when JavaScript manipulates the value via element.value = newValue, and you want the change event to be fired, then the JavaScript should explicitly call element.change() on the input element being manipulated.
According to $.multiDatesPicker documentation, you can use the onSelect option to hook a function on select. In that function you can then just call element.change(). So, given an input as follows:
<h:inputText ... styleClass="multi-dates" />
then you can achieve it as follows:
$(".multi-dates").multiDatesPicker({
onSelect: function() {
$(this).change();
}
});

Related

JSF SelectOneMenu onchange, onsubmit cancel reset value

On a JSF SelectOneMenu, I have ajax event onchange, and with an onsubmit with a confirm question, when user abort the change, how could I reset the value on SelectOneMenu back to the original value?
<h:selectOneMenu value="#{bean.selectedFruit}">
<f:selectItems value="#{bean.fruits}"/>
<a:support event="onchange" onsubmit="if(!confirm('Are you sure?'))return false;}" action="#{bean.loadFruitStats}" rerender="body"/>
</h:selectOneMenu>
So on the above example, when user click 'No' on the confirm dialog, the action is not called, and rerender is not called, so the SelctOneMenu is on the updated "fruit" name, not the original one (so the fruit name and the fruit stats info doesnt match). What can I do to synchronize them?
h:selectOneMenu can be reset back to the original value with a help of javascript.
First you will need to define an id to h:selectOneMenu. For example
<h:selectOneMenu id="selFruitId"...>
Add following (self-explanatory) java script to jsf page
var currentValue;
function saveCurrentValue(){
//get html select element
var element=document.getElementById("form:selFruitId");
//saves currently selected value
currentValue=element.value;
}
function areYouSure(){
if(!confirm('Are you sure?')){
//if canceled, restores previously saved value
document.getElementById("form:selFruitId").value=currentValue;
return false;
}
}
Then you need to intercept moment when user tries to change selected value using mouse (onclick event) or keyboard (onkeypress event, for example, left-right-up-down cursor keys or some other key) and save currently selected value for later.
<h:selectOneMenu id="selFruitId"
onclick="saveCurrentValue()" onkeypress="saveCurrentValue()"...>
And, finally, before executing ajax, you need to call function areYouSure() which will, if canceled, restore saved (original) value back to h:selectOneMenu.
<h:selectOneMenu value="#{bean.selectedFruit}" id="selFruitId"
onclick="saveCurrentValue()" onkeypress="saveCurrentValue()">
<f:selectItems value="#{bean.fruits}"/>
<a:support event="onchange" onsubmit="areYouSure()" action="#{bean.loadFruitStats}" rerender="body"/>
</h:selectOneMenu>

Do something after widgetVar.filter() is really completed and has updated p:datatable

I have a datatable (primefaces 4.0), and I'm using widgetVar to apply re-filter table after update of data.
I need to call function doSomething() ONLY when employeesDataTable_WV.filter(); has really finished to filter table and update it.
in this link is show how work filter function
https://searchcode.com/codesearch/view/2686053/
it seems to do an ajax request and than update the component.
Here my example code
<h:form id="form">
<p:remoteCommand name="myRemote" actionListener="viewEmployeesManagedBean.refreshEmployees"
update=":form:employeesDataTable"
oncomplete="employeesDataTable_WV.filter();doSomething();"/>
<p:dataTable id="employeesDataTable"
value="#{viewEmployeesManagedBean.employees}" var="employee" widgetVar="employeesDataTable_WV">
[...]
</p:dataTable>
</h:form>
I need to call doSomething function ONLY after datatable is filtered and updated by employeesDataTable_WV.filter() function.
All my tests did not work and the doSomething function is always invoked before the update of the datatable.
Thanks a lot for any help.
What you should do is to add a ajax event handler to the p:dataTable and put the doSomething() in the oncomplete of the filter event and remove it from the p:remoteCommand.
<p:ajax event="filter" oncomplete="doSomething()" />
If you do not want/need to have a roundTrip to the server, you can replace the p:ajax with the PrimeFaces Extensions pe:javascript
And if you only want it to happen when the filter() is called directly on the widgetVar, just set a semaphore directly before calling the filter() and check in the doSomething() if it was set.
<p:remoteCommand ...
oncomplete="mySemaphore = true;employeesDataTable_WV.filter();"/>
function doSomething() {
if(mySemaphore == true;) {
...
mySemaphore = false;
}
// just do nothing if called from editing in one of the filter fields
}
This should work for 4.0 but also for later versions up to the current (at time of answering) 6.1-SNAPSHOT (and most likely beyond)
See also
How can I capture the event filtering a datatable in primefaces

SelectOneMenu fire ajax when up or down arrow key is pressed

I need to fire an ajax call when i hit the up arrow key or the down arrow key when im focused on the selectOneMenu.
Here is my code, i tried only with the up key first (Its not working, and i tried several variations)
<h:selectOneMenu id="id" disabled="#!Bean.disabled}" value="#{Bean.value}" styleClass="style" onkeypress="if (event.keyCode == 38) { onchange(); return false; }">
<f:selectItems id="idItem" value="#{Bean.options}" var="option" />
<f:ajax event="change" execute="#this" render="group"/>
</h:selectOneMenu>
Hint: Tab key is firing it and moving the focus (if the value changed). I dont want the tab key firing it.
Just change the event of your f:ajax to keyup, the change event will not send any ajax request unless your selectOneMenu loses focus (that's also confirmed by your hint "Tab key is firing it and moving the focus ").
That will work like this:
<f:ajax event="keyup" execute="#this" render="group"/>
Update:
I updated my answer following BalusC's comment that the you want the ajax request to be fired only if the up Key or down Key are fired, so i am suggesting you to invoke directly the javascript function that f:ajax calls behind the scenes, So you can add a direct call to jsf.ajax.request(source, event, options) function, you can find more informations about that function here.
In order to use that method you must add the JSF’s built-in JavaScript library in your XHTML files like this:
<h:outputScript library="javax.faces" name="jsf.js"/>
Then change your code like this:
<h:selectOneMenu id="id" disabled="#!Bean.disabled}" value="#{Bean.value}" styleClass="style"
onkeyup="if (event.keyCode == 38 || event.keyCode == 40) { jsf.ajax.request(this, event, { render: 'form:group'}); return false;}">
<f:selectItems id="idItem" value="#{Bean.options}" var="option" />
</h:selectOneMenu>
NB: Please notice that in the render option of the jsf.ajax.request() i specified the exact ClientID of the component you want to render and not only the component id (form is here the id of h:form), if you want to use only the id group you must add prependId="false" to your h:form.

simulate onclick event picklist primefaces

I know that the primefaces picklist only alows transfer event like
<p:ajax event="transfer" listener="#{bean.onTransfer}" />
But I am looking for an onTargetSelected event. Is there a way to simulate it?
I thought about a JQuery function bound with a click event but I don't know on which element. I saw that when I select a line in the target list, the class of the li is transforming to ui-state-highlight. Is there a way to detect class changing with JQuery?
To call a bean method when the event will be fired, I thought about primefaces remoteCommand to send the ID of my object.
Do you have an idea about this event?
Note: I saw that there is a select with the target values in the source code but the selected value is 'selected' for each item and I don't know if there is something to do with this.
Thanks for your help
I have a trick. I am using this JQuery function :
$(document).ready(function(){
$('.ui-picklist-target .ui-picklist-item td').click(function() {
var id = $(this).closest("li").attr("data-item-value");
$('[id$=selectedItemId]').val(id); // Setting the value of my hidden input
updateSelectedTarget(); // Calling the remoteCommand function
});
});
I have added this to my xhtml page
<h:form>
...
<p:pickList ...>
</p:pickList>
<h:inputHidden id="selectedItemId" value="#{modifierUOBean.selectedTargetId}"/>
<p:remoteCommand name="updateSelectedTarget" actionListener="#{modifierUOBean.onSelectedTarget}"/>
</h:form>
And the bean:
private int selectedTargetId; // and getters and setters
public void onSelectedTarget() {
// Do what you want with selectedTargetId which contains the id of selected item
}

selectOneMenu ajax events

I am using an editable primefaces selectOneMenu to display some values. If the user selects an item from the List a textarea should be updated. However, if the user types something in the selectOneMenu, the textarea should not be updated.
I thought I could work this with ajax event out. However, I don't know which event I can use here. I only know the valueChange event. Are there any other events, like onSelect or onKeyUp?
Here is my code:
<p:selectOneMenu id="betreff" style="width: 470px !important;"
editable="true" value="#{post.aktNachricht.subject}">
<p:ajax event="valueChange" update="msgtext"
listener="#{post.subjectSelectionChanged}" />
<f:selectItems value="#{post.subjectList}" />
</p:selectOneMenu>
<p:inputTextarea style="width:550px;" rows="15" id="msgtext"
value="#{post.aktNachricht.text}" />
The PrimeFaces ajax events sometimes are very poorly documented, so in most cases you must go to the source code and check yourself.
p:selectOneMenu supports change event:
<p:selectOneMenu ..>
<p:ajax event="change" update="msgtext"
listener="#{post.subjectSelectionChanged}" />
<!--...-->
</p:selectOneMenu>
which triggers listener with AjaxBehaviorEvent as argument in signature:
public void subjectSelectionChanged(final AjaxBehaviorEvent event) {...}
I'd rather use more convenient itemSelect event. With this event you can use org.primefaces.event.SelectEvent objects in your listener.
<p:selectOneMenu ...>
<p:ajax event="itemSelect"
update="messages"
listener="#{beanMB.onItemSelectedListener}"/>
</p:selectOneMenu>
With such listener:
public void onItemSelectedListener(SelectEvent event){
MyItem selectedItem = (MyItem) event.getObject();
//do something with selected value
}
Be carefull that the page does not contain any empty component which has "required" attribute as "true" before your selectOneMenu component running.
If you use a component such as
<p:inputText label="Nm:" id="id_name" value="#{ myHelper.name}" required="true"/>
then,
<p:selectOneMenu .....></p:selectOneMenu>
and forget to fill the required component, ajax listener of selectoneMenu cannot be executed.
You could check whether the value of your selectOneMenu component belongs to the list of subjects.
Namely:
public void subjectSelectionChanged() {
// Cancel if subject is manually written
if (!subjectList.contains(aktNachricht.subject)) { return; }
// Write your code here in case the user selected (or wrote) an item of the list
// ....
}
Supposedly subjectList is a collection type, like ArrayList. Of course here your code will run in case the user writes an item of your selectOneMenu list.

Resources