Primefaces calendar not firing dateSelect - jsf

I'm trying to get a value from my calendar via ajax.
xhtml portion:
<p:calendar
id="newSimFrom"
value="#{SimModel.from}" <!-- this works -->
showOn="button"
mask="true"
pattern="dd.MM.yyyy"
>
<p:ajax event="dateSelect" process="#this" update="newSimUnt" listener="#{SimController.simFromChanged()}" />
</p:calendar>
controller:
public void simFromChanged(SelectEvent se) {
log.info("called");
log.info(""+se.getObject());
//this is temporary till I can figure out what's even going on
}
But I get nothing, no event seems to be fired.
I've also tried event="change" as well as event="select" and process="#this" (latter as suggested by https://stackoverflow.com/a/42295586)
Also, I've tried to put the listener on with and without the parenthesises, didn't seem to make any differences.
The calendar is inside a form tag. (Kinda, there's 2 layers if <div> above, does that make a difference?) (https://stackoverflow.com/a/17213127/7591918)
Any ideas where I should go to for debugging what's going on? I'm relatively new to Primefaces and JSF as a whole, my IDE's console and my browser console don't give me any errors.
Thanks!

The method in your listener isn't spelled correctly. You forgot the "new".
If you want to get the event don't use parentheses.
The event you get is a DateSelectEvent, so this should work:
xhtml:
<p:ajax event="dateSelect" process="#this" update="newSimUnt" listener="#{SimController.newSimFromChanged}" />
controller:
public void newSimFromChanged(DateSelectEvent se) {
log.info("called");
log.info("" + se.getDate());
//this is temporary till I can figure out what's even going on
}
If that doesn't work the error must be somewhere else.

Wep0n, try these examples:
<p:calendar id="newSimFrom" value="#{SimModel.from}"
showOn="button" mask="true" pattern="dd.MM.yyyy">
<p:ajax event="dateSelect" update="newSimUnt"
listener="#{SimController.simFromSelected}" />
<f:ajax event="change" execute="#this" render="newSimUnt"
listener="#{SimController.simFromChanged}"/>
</p:calendar>
And inside your managedBean SimController:
public void simFromSelected(DateSelectEvent event) {
System.out.println("DateSelectEvent " + event.getDate());
}
public void simFromChanged(AjaxBehaviorEvent event) throws MWSException {
System.out.println("AjaxBehaviorEvent " + event.getDate());
}

So Apparently, my problem was with how Spring internally addresses classes, or rather how the automatic name generation works, as I did not explicitly name the bean.
listener="#{SimController.newSimFromChanged}"
was changed to
listener="#{simController.newSimFromChanged}"
(note the lowercase s)
And now it works.
This is pretty unintuitive (IMO), and I'm not sure this is universally applicable but I'm going to leave this here if someone else ever has the same problem. Do note that this also does not apply if your class starts with multiple uppercase letters, if I had named my class SIMController it would have worked right away.

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>

p:datePicker dateSelect event on empty dates

I have two p:datePicker and they work fine:
<p:outputLabel for="filterStartDate" value="Start Date:" />
<p:datePicker id="filterStartDate" value="#{historyController.filterStartDate}" timeOnly="true" pattern="HH:mm" converter="#{localTimeConverter}">
<p:ajax event="dateSelect" listener="#{historyController.filterStartDateSelect}"/>
</p:datePicker>
<p:outputLabel for="filterEndDate" value="End Date:" />
<p:datePicker id="filterEndDate" value="#{historyController.filterEndDate}" timeOnly="true" pattern="HH:mm" converter="#{localTimeConverter}">
<p:ajax event="dateSelect" listener="#{historyController.filterEndDateSelect}"/>
</p:datePicker>
On my backend my methods who catch the ajax event are:
private LocalTime filterStartDate;
private LocalTime filterEndDate;
public void filterStartDateSelect(SelectEvent event) {
filterStartDate = ((LocalTime) event.getObject());
}
public void filterEndDateSelect(SelectEvent event) {
filterEndDate = ((LocalTime) event.getObject());
}
This works fine, the problem is when I want to initialize the objects filterStartDate and filterEndDate to null. The ajax event dateSelect it's never called when the value is empty.
If you take a look at the "Ajax Behavior Events" section of the p:datePicker documentation, you'll see that the only explicitly documented event is dateSelect. But there is a note:
In popup mode, DatePicker also supports regular ajax behavior events like blur, keyup and more.
So you can add an Ajax listener and handle all the changes and use that to handle null values. Or only use the change event to handle all changes, which saves you extra Ajax calls being made to the server.

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 update attribute of p:remoteCommand works

Primefaces 6.0. I understand that update attribute of p:remoteCommand should be used to specify clientIds of the components that should be updated by AJAX. I am trying to understand how PF works. In combination with DataTable it doesn't seem to work as expected. When I try to directly set update="form:dataTable:2:bColumn", it has no efect. However, doing this (commented out in the below code) RequestContext.getCurrentInstance().update("form:dataTable:2:bColumn"); will force PF to update the specified outputText.
Why is this happening? I will be happy for technical explanation - I am trying to find the answer by debugging PF Java/Javascript sources.
<h:form id="form">
<p:remoteCommand name="remoteCall"
action="#{grid4.onEdit}"
update="form:dataTable:2:bColumn"
/>
<p:dataTable id="dataTable"
var="gridItem"
value="#{grid4.gridItems}"
editable="true" editMode="cell"
>
<p:ajax event="cellEdit"
oncomplete="remoteCall()">
</p:ajax>
<p:column headerText="A">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{gridItem.a}" /></f:facet>
<f:facet name="input"><p:inputText value="#{gridItem.a}"/></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="B">
<h:outputText id="bColumn" value="#{gridItem.b}" />
</p:column>
</p:dataTable>
</h:form>
Bean
#ManagedBean
#ViewScoped
public class Grid4 {
private List<GridItem> gridItems = new ArrayList<>();
public Grid4() {
gridItems.add(new GridItem("1", "a","b"));
gridItems.add(new GridItem("2", "a","b"));
gridItems.add(new GridItem("3", "a","b"));
}
public void onEdit() {
System.out.println("onEdit()");
gridItems.get(2).setB("CHANGED VALUE");
// RequestContext.getCurrentInstance().update("form:dataTable:2:bColumn");
}
public List<GridItem> getGridItems() {
return gridItems;
}
public void setGridItems(List<GridItem> gridItems) {
this.gridItems = gridItems;
}
}
basically jsf ids an client side ids are two different things (check this answer and this post for a better understanding).
When you use RequestContext.getCurrentInstance().update("form:dataTable:2:bColumn"); that method use the client id to find the components that have to be updated, but in the case of the update property of p:remoteCommand it is expecting a jsf id, not the generated client id, so that´s why your update doesn't work. However, primefaces support jquery selectors to update components, so you could use a client side id on an update property like this update="#(#yourElementId)"
Let me start by mentioning that this is not specific to the p:remoteCommand. The reason for the behaviour you notice is rather simple although not directly obvious maybe since it is unfortunately not in the PrimeFaces documentation.
The update attribute in:
<p:remoteCommand name="remoteCall"
action="#{grid4.onEdit}"
update="form:dataTable:2:bColumn"
/>
uses a relative path if it does not start with a : and since the p:remoteCommand is already in the naming container with id='form', the form in the update attribute is superfluous and even makes it not work (run your app in dev mode, add a messages tag and see the errors).
So
<p:remoteCommand name="remoteCall"
action="#{grid4.onEdit}"
update="dataTable:2:bColumn"
/>
Should work, as should
<p:remoteCommand name="remoteCall"
action="#{grid4.onEdit}"
update=":form:dataTable:2:bColumn"
/>
The
RequestContext.getCurrentInstance().update("form:dataTable:2:bColumn");
is always absolute, so the colon is not needed here and it will find the element starting from the root (form 'prefix' is needed then)

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.

Resources