Ajax Conditional update on Primefaces - jsf

Is it possible to do a conditional update with Ajax. I have two calendar components and the code is as follows
Calendar component 1 (workDate)
<h:outputLabel value="#{lbl.WorkDate}" for="workDate" rendered="#{!userManager.customerUser}"/>
<p:calendar id="workDate" value="#{jobs_Builder.selected.workDate}" pattern="dd/MM/yyyy" mask="true" rendered="#{!userManager.customerUser}" mindate="Date()">
<p:ajax event="dateSelect" update="requestedDeliveryDate" />
</p:calendar>
Calendar component 2(requestedDeliveryDate)
<h:outputLabel value="#{lbl.RequestedDeliveryDate}" for="requestedDeliveryDate" rendered="#{!userManager.customerUser}"/>
<p:calendar id="requestedDeliveryDate" value="#{jobs_Builder.selected.requestedDeliveryDate}" pattern="dd/MM/yyyy" mask="true" rendered="#{!userManager.customerUser}" mindate="#{jobs_Builder.selected.workDate}"/>
The behavior is whenever the date is set in wordkdate, the requestedDeliveryDate is reset, but what I want is to get that reset only if the requestedDeliveryDate is earlier than the workDate.
Is this something which I can do?

Change your dateSelect event not to update anything but use a Java listener instead like..
<p:ajax event="dateSelect" listener="#{controller.onDateSelect}" />
In your Java method check for your two dates and if your condition is met update the UI component from this method.
public void onDateSelect() {
if (date1 > date2) {
// update other calendar
PrimeFaces.current().ajax().update("requestedDeliveryDate");
}
}

Related

How to update model on change / date select of p:calendar [duplicate]

I'm try to use the primefaces calendar with popup in this way:
<p:calendar pattern="yyyy-MMM-dd" value="#{controller.beginDate}" mask="true" navigator="true">
<f:ajax event="valueChange" listener="#{controller.onChange}" />
</p:calendar>
And here is the relative controller:
#ManagedBean
public class Controller {
private Date beginDate;
public Date getBeginDate() {
return beginDate;
}
public void setBeginDate(Date beginDate) {
this.beginDate = beginDate;
}
public void onChange() {
// do somethings
}
}
The problem: if I change the value from the input field, the event will be execute, but if I change it from the popup, the event will NOT execute.
Can anyone help me?
The valueChange event is only triggered by HTML DOM change event. This is indeed not triggered when the input value is manipulated by JavaScript means.
You need the dateSelect event instead. And, in PrimeFaces components, you'd better use <p:ajax> instead of <f:ajax>.
<p:calendar ...>
<p:ajax event="valueChange" listener="#{controller.onChange()}" />
<p:ajax event="dateSelect" listener="#{controller.onChange()}" />
</p:calendar>
See also:
PrimeFaces Users Guide
Try using the PrimeFaces dateSelect event.
From PrimeFaces documentation:
Calendar provides a dateSelect ajax behavior event to execute an instant ajax selection whenever a date is selected. If you define a method as a listener, it will be invoked by passing an org.primefaces.event.SelectEvent instance.
<p:calendar value="#{calendarBean.date}">
<p:ajax event="dateSelect" listener="#{bean.handleDateSelect}" />
</p:calendar>

Primefaces calendar does not set the date

I have yet another misunderstanding of Primefaces work logic.
For now <p:calendar> component cannot set selected date when I press submit button.
I see that it successfully enters into actionListener method, but date value is null there.
First of all I tried create my calendar using standard PF example. It looked too simple and I thought according this that the component should call value setter when the user select the date or submit the form. But it did it neither in the first nor in the second case.
Well, I opened Google and found a few posts:
Primefaces Calendar Setting Date Value in Backing Bean
p:calendar value not set in backing bean
I ensured that my calendar is located between <h:form></h:form> tags. Also I tried to add process="#this" and process=":beginDateForm :endDateForm #this", where beginDateForm and endDateForm are forms contained <p:calendar> components.
Also I found the post and tried to create SelectEvent listener method:
private void changeDate(SelectEvent event) {
beginDate = (Date) event.getObject();
}
But unsuccessfully.
I also tried to change Date using valueChangeListener:
<h:form id="beginDateForm">
<p:calendar id="passBeginDate" valueChangeListener="#{territoryFormBean.changeDate}" mode="popup" readonly="true" pattern="dd.MM.yyyy" showOn="button" value="#{territoryFormBean.beginDate}" />
</h:form>
Of course I changed event to ValueChangeEvent.
After that I moved <p:calendar> and <p:commandButton> components into the same <h:form> and tried two different process values process="passTerrForm:passBeginDate passTerrForm:passEndDate #this" and process="#form #this" and process="#form"
In the last case button does not trigger even the listener method.
My current components are:
<p:commandButton value="Search" id="searchPassButton" actionListener="#{territoryFormBean.search}" update=":passTerrForm:territoryTable" process="passTerrForm:passBeginDate passTerrForm:passEndDate #this" partialSubmit="true" />
<p:column>
<p:calendar id="passBeginDate" mode="popup" readonly="true" pattern="dd.MM.yyyy" showOn="button" value="#{territoryFormBean.beginDate}" />
</p:column>
<p:column>
<p:calendar id="passEndDate" mode="popup" readonly="true" pattern="dd.MM.yyyy" showOn="button" value="#{territoryFormBean.endDate}" />
</p:column>
Guys, could you please suggest anything else. Or probably you can see what is wrong in my code.
I cannot understand why the component does not call setter.
Well, guys, I found my mistake. Stupid mistake. Yet another re-read the PF documentation showed that using readonly parameter is incorrect for my goals. I wanted to prevent the manual date input directly into <p:calendar> text field. But according the documentation:
readonly -
Flag indicating that this input element will prevent changes by the
user
But I need readonlyInput parameter which
Makes input text of a popup calendar readonly.
So the second parameter prevents input, while the first one prevents changes totally.
Thank you for your help.
Trying to make an analogy with a code that I have, I think that putting the button into the same form as the calendar, and omitting the 'process' and 'partialSubmit' should work:
<h:form id="beginDateForm">
<p:calendar id="passBeginDate" valueChangeListener="#{territoryFormBean.changeDate}" mode="popup" readonly="true" pattern="dd.MM.yyyy" showOn="button" value="#{territoryFormBean.beginDate}" />
<p:commandButton value="Search" id="searchPassButton" actionListener="#{territoryFormBean.search}" update=":passTerrForm:territoryTable" />
</h:form>
I hope it helps!
JSF Code:
<p:calendar id="from" value="#{pageBean.event.startDate}" pattern="MM/dd/yyyy hh:mm:ss a" timeZone="GMT-4"/>
<p:commandButton id="addButton" value="Save" actionListener="#{pageBean.addEvent}" update=":#form"/>
You can write an addEvent method in the Bean where you need to add these calendar event to an eventModel and save it. This helps you to set the date and you can retrieve it as and when you need.
Java Code:
private ScheduleModel eventModel;
private ScheduleEvent event = new DefaultScheduleEvent();
public String addEvent(ActionEvent actionEvent) {
if(event.getId() == null){
eventModel.addEvent(event);
}
}
Hope this helps!!

How do I force a Primefaces calendar to update after a change Ajax event validates the new value?

I'm modifying a page with two Calendar components, to select a start date and an end date. I'm supposed to make them check that the start date is before the end date whenever you modify either of them; if the start is set after the end or viceversa, the code changes the end date to the maximum date and pops a warning.
The event listeners run correctly, but the end date calendar fails to update to reflect the new value; it's not that it updates before the listener changes the value ─it fails to update at all.
The project runs on Primefaces 5.3 and Java 1.6. This is the xhtml (minus styles for readability):
<p:outputPanel id="fl83">
<p:outputPanel id="fl83c3">
<h:outputLabel value="Start date" for="fechaInicioMP" />
<p:calendar locale="es" pattern="dd/MM/yyyy" id="fechaInicioMP"
maxdate="#{filtroFechasBB.fechaMaxFin}" value="#{filtroFechasBB.fechaInicio}"
onSelectUpdate=":f183" >
<p:ajax event="blur" />
<f:ajax event="change" listener="#{filtroFechasBB.fechaInicioTextChange}"
render="#this" update="#form" />
<p:ajax event="dateSelect" listener="#{filtroFechasBB.fechaInicioClickChange}"
update="#form" />
</p:calendar>
</p:outputPanel>
<p:outputPanel id="fl83c4">
<h:outputLabel value="End date" for="fechaFinMP" />
<p:calendar locale="es" pattern="dd/MM/yyyy" id="fechaFinMP"
maxdate="#{filtroFechasBB.fechaMaxFin}" value="#{filtroFechasBB.fechaFin}"
onSelectUpdate=":f183" >
<p:ajax event="blur" />
<f:ajax event="change" listener="#{filtroFechasBB.fechaFinTextChange}"
render="#this" update=":fl83" />
<p:ajax event="dateSelect" listener="#{filtroFechasBB.fechaFinClickChange}"
update=":fl83" />
</p:calendar>
</p:outputPanel>
</p:outputPanel>
And these are the listeners:
public void fechaFinTextChange() {
if(fechaFin.after(fechaMaxFin)) {
fechaFin = fechaMaxFin;
addErrorMessage(FFIN_AFTER_FMAX);
}
compareInicioBeforeFin();
}
public void fechaFinClickChange(SelectEvent event) {
setFechaFin((Date)event.getObject()); // I couldn't find out why this is here given that
// the setter has already been called
compareInicioBeforeFin();
if (updateMetodoEntreBB != null) {
ajaxActualiza(event, OpcionesAjax.F_FIN);
}
}
// fechaInicioTextChange and fechaInicioClickChange do pretty much the same as these two
private void compareInicioBeforeFin() {
if(fechaInicio.after(fechaFin)) {
fechaFin = fechaMaxFin;
addErrorMessage(FINI_AFTER_FFIN);
}
}
There are two Ajax events because the JSF change event doesn't trigger when you click on the calendar and the PrimeFaces dateSelect doesn't trigger when you type a date in.
I've tried the onSelectUpdate from the calendar and the render and update from both ajax events, setting them to #this, #form, the end date calendar's ID, both calendars' IDs, the calendar's outputPanel's ID and the common outputPanel's ID, and the damn calendars just. Won't Update.
I'm at my wits' end and my Google Fu doesn't find any solution that works either.
You need to set an ajax event on the click of the start date calendar :
<p:calendar id="start_date" pattern="dd/MM/yyyy HH:mm" value="#{managedBean.startDate}" size="20" >
<p:ajax event="dateSelect" listener="#{managedBean.onSelectDate()}" update=":form:end_date" />
</p:calendar>
<p:calendar id="end_date" pattern="dd/MM/yyyy HH:mm" mindate="#{managedBean.startDate}" value="#{managedBean.endDate}" size="20" />
When you select the startDate that triggers a method where you set endDate to null, and you update the endDate calendar, which is limited by mindate="#{managedBean.startDate}"
public void onSelectDate() {
this.setEndDate(null);
}
First of all: f:ajax doesn't have an update attribute, in f:ajax you need to use the render attribute.
A p:remoteCommand with the ajax oncomplete Attribute should solve the problem:
<p:outputPanel id="fl83">
<p:remoteCommand name="updateCalendar" update="fl83" />
<p:outputPanel id="fl83c3">
<h:outputLabel value="Start date" for="fechaInicioMP" />
<p:calendar locale="es" pattern="dd/MM/yyyy" id="fechaInicioMP"
maxdate="#{filtroFechasBB.fechaMaxFin}" value="#{filtroFechasBB.fechaInicio}"
onSelectUpdate=":f183" >
<p:ajax event="blur" />
<f:ajax event="change" listener="#{filtroFechasBB.fechaInicioTextChange}"
oncomplete="updateCalendar()" />
<p:ajax event="dateSelect" listener="#{filtroFechasBB.fechaInicioClickChange}"
oncomplete="updateCalendar()" />
</p:calendar>
</p:outputPanel>
<p:outputPanel id="fl83c4">
<h:outputLabel value="End date" for="fechaFinMP" />
<p:calendar locale="es" pattern="dd/MM/yyyy" id="fechaFinMP"
maxdate="#{filtroFechasBB.fechaMaxFin}" value="#{filtroFechasBB.fechaFin}"
onSelectUpdate="f183" >
<p:ajax event="blur" />
<f:ajax event="change" listener="#{filtroFechasBB.fechaFinTextChange}"
oncomplete="updateCalendar()" />
<p:ajax event="dateSelect" listener="#{filtroFechasBB.fechaFinClickChange}"
oncomplete="updateCalendar()" />
</p:calendar>
</p:outputPanel>
</p:outputPanel>
If that doesn't solve the problem: do you've a form around it which modifies the ids? If you've a without prependId="false" form1 is prepend to every id inside the form. So you'd need to access the panel with exampleForm:fl83.

how to get value of primefaces calendar in managed bean?

i have a calendar in my jsf page that i want to get his value when its changed i tryed to add listener but didnt work i found other solutions but didnt work with primefaces 3.5:
<p:calendar id="popupButtonCal22" value="#{zp01ManagedBean.datedeplanification}" showOn="button" locale="fr" >
<p:ajax listener="#{zp01ManagedBean.setDatedeplanification(zp01ManagedBean.datedeplanification)}"/>
</p:calendar>
do you know how to fixe this problem ?
i am using primefaces 3.5
<p:ajax partialSubmit="true"/> works with inputText.
<p:ajax event="dateSelect"/> works with calendar when is selected a date.
<p:ajax event="change"/> works with calendar when is typed a date.
It is not necessary to set the value manually by an ajax listener, as the setter is implicitly called when the value of the field is submitted. All you have to do is to submit the value on change. So try this:
<p:calendar id="popupButtonCal22" value="#{zp01ManagedBean.datedeplanification}" showOn="button" locale="fr" >
<p:ajax process="popupButtonCal22" partialSubmit="true" event="change"/>
</p:calendar>
If you would additionally like to call an action after the value changed you can add listener="#{someBean.someAction" to the p:ajax-tag.
And if you would like to do some checks with the old and the new value use the valueChangeListener-attribute of the p:calendar-tag.
Try to put the p:calendar component in a h:form tag. I don't see why your code won't work actually, you do not even need ajax for that...
Try This, May be this can Help:
<h:body>
<h:form>
<p:calendar id="dateObj" value="#{test.date1}" showOn="button" pattern="dd-MMMM-yyyy">
<p:ajax event="dateSelect" listener="#{test.handleDateSelect}"/>
</p:calendar>
</h:form>
</h:body>
The Bean is like that:
private Date date1;
public Date getDate1() {
return date1;
}
public void setDate1(Date date1) {
this.date1 = date1;
}
public void handleDateSelect(DateSelectEvent event){
System.out.println(event.getDate());
}
<p:calendar ...>
<p:ajax event="dateSelect" ... />
<p:ajax event="change" ... />
</p:calendar>
This works for me.

PrimeFaces p:calendar with readonlyInput="true" reset button causing no AJAX request

Since there's no attribute/option for <p:calendar> (readonlyInput="true") to reset the value to null, the best available solution currently is to use some client JS to reset the value like here:
https://stackoverflow.com/a/12325640/396732
However, as soon as the clear button controls an AJAX button, the new calendar value isn't submitted.
I tried to process the end-date button, like:
<p:calendar id="end-date"
widgetVar="myEntityEndDate"
value="#{myEntityManager.selectedEndDate}"
readonlyInput="true"
showOn="button">
<!-- update dependent "begin" calendar component: -->
<p:ajax event="dateSelect" process="#this" update="begin-date" />
</p:calendar>
<p:commandButton icon="ui-icon ui-icon-close"
onclick="myEntityEndDate.setDate(null);"
process="end-date"
update="begin-date end-date" />
However it isn't working...
Q:
How do you implement a reset button for an AJAXed p:calendar component?
Addendum:
The same question was asked here: http://forum.primefaces.org/viewtopic.php?f=3&t=27821 . It seems like jQuery could be the "guilty party". Anyways, it should be solved/solvable IMHO.
If you want the reset will be reflected on the server you should use the action of p:commandButton
<p:commandButton icon="ui-icon ui-icon-close"
action="#{myEntityManager.resetDate}"
process="end-date"
update="begin-date end-date" />
public void resetDate(){
selectedEndDate = null;
}

Resources