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!!
Related
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.
I've the following form:
<h:form>
<h:inputText size="2" value="#{orderMB.quantity}" />
<h:outputLabel value=" #{orderMB.totalPriceOneItem} €" />
<h:commandButton value="submit" />
</h:form>
And I've the following method in a session scoped managed bean:
public void setQuantity(int quantity) {
this.quantity = quantity;
setTotalPriceOneItem(quantity* item.getItem().getPrice().doubleValue());
}
I would like to auto-update the total price result on every key press of the input field. How can I achieve this without pressing the submit button?
Your code isn't doing that anywhere. It's missing a <f:ajax>.
<h:inputText size="2" value="#{orderMB.quantity}">
<f:ajax event="keyup" render="total" />
</h:inputText>
<h:outputText id="total" value="#{orderMB.totalPriceOneItem} €" />
The event attribute can be set to any HTML DOM event on which JSF must submit the form by ajax, such as click, keyup, blur, focus, etc. The render attribute can be set to any JSF client ID which needs to be updated when the ajax submit finishes. In this case it's referring the ID of the component showing total price.
Note that I replaced the wrong <h:outputLabel> by <h:outputText>. Also noted should be that a setter isn't exactly the right place to perform business logic (a getter also not!). Better revert that setter method to a true setter and add an ajax listener method:
<f:ajax event="keyup" listener="#{orderMB.updateTotalPriceOneItem}" render="total" />
public void updateTotalPriceOneItem() {
totalPriceOneItem = quantity * item.getItem().getPrice().doubleValue();
}
In case when it still doesn't work, then verify if you have a <h:head> in the template instead of a <head>. If still in vain, work through commandButton/commandLink/ajax action/listener method not invoked or input value not updated.
That said, I strongly recommend to take a pause and work through a sane JSF 2.x book. The above is usually already covered in the 1st chapter.
I'm trying to block a <p:commandButton> which is displayed on a <p:confirmDialog> as follows.
<p:confirmDialog id="confirmDeleteDialog" widgetVar="confirmDelete" message="Message" closeOnEscape="true" appendTo="#(body)" closable="true">
<p:blockUI block="confirm" widgetVar="blockUI">
<h:outputText value="Demo"/>
</p:blockUI>
<p:commandButton id="confirm" value="Yes" onstart="PF('blockUI').show()" oncomplete="PF('blockUI').hide();"/> <!--Use PF('confirmDelete').hide() to dismiss the dialog.-->
<p:commandButton id="decline" value="No" onclick="PF('confirmDelete').hide()" type="button" />
</p:confirmDialog>
<p:commandButton oncomplete="PF('confirmDelete').show()"/>
This blocks Yes button (one with the id="confirm") held by <p:confirmDialog>.
The message to be displayed on the confirm dialog is dynamic. It is fetched from the associated backing bean based on certain conditions. Therefore, the dialog is required to be updated before it is displayed.
To update the dialog before it is displayed, the update attribute of <p:commandButton> is set as follows.
<p:commandButton oncomplete="PF('confirmDelete').show()" update="confirmDeleteDialog"/>
This of course, displays a desired message on the dialog dynamically (which is not demonstrated here for the sake of simplicity) but doing so prevents the <p:blockUI> from functioning - it does not block the <p:commandButton>, if the dialog is updated by it.
Neither errors on the browser console nor exceptions on the server terminal are seen.
What is the way of blocking a button held by a in addition to displaying a dynamic message on the dialog?
EDIT :- the answer provided by me is cross-mark.
As noted in the answer given by me, <p/pe:blockUI> needs to be updated, when the <p:commandButton> held by the confirm dialog is clicked, it takes some time to block the button - <p:commandButton> after it is clicked. In the meanwhile, the button can be clicked (either deliberately or accidently) before the initial request completes that may cause duplicate submits which is certainly against the use of <p/pe:blockUI>.
Nothing is preventing a user in my workaround, from clicking the button multiple times before it is blocked by <p/pe:blockUI>. Therefore, the answer provided by me is considered to be cross-mark.
Perhaps the way to meet this requirement is completely different.
EDIT 2:- the actual scenario.
//A view scoped bean.
//A list of selected rows in <p:dataTable>.
private List<WishUtils>selectedValues;
//The actual message to be displayed on the dialog.
private String deleteMsg;
//Associated with the rendered property of the "Yes" button on the dialog.
private boolean renderedYesButtonDelete=true;
//The header message/text of the dialog.
private String messageBoxHeader;
//The no button text (its value).
private String noButtonTextDelete="No";
//Getters and setters as required.
public void confirmDelete(ActionEvent actionEvent) {
if(selectedValues!=null && !selectedValues.isEmpty()) {
renderedYesButtonDelete=true;
noButtonTextDelete="No";
deleteMsg="A long message about a delete prompt from a resource bundle";
messageBoxHeader="Confirm Delete";
} else {
noButtonTextDelete="OK";
renderedYesButtonDelete=false;
deleteMsg="Please select the rows you want to delete";
messageBoxHeader="Confirm Item Select";
}
}
public void delete(ActionEvent actionEvent) {
if(actionEvent.getComponent().getId().equals("confirmDeleteMultiple")) {
//Delete the selected rows.
} else {
//Notify an error (generally never going to be executed).
}
}
The message box goes here :
<p:confirmDialog id="confirmDialogDeleteMultiple" widgetVar="confirmDeleteUIWidget" header="#{wishManagedBean.messageBoxHeader}" closeOnEscape="true" appendTo="#(body)" closable="true">
<p:blockUI id="blockDelete" block="confirmDeleteMultiple" widgetVar="blockDeleteUIWidget"/>
<p:remoteCommand name="blockDeleteCommand" update="blockDelete" process="#this"/>
<p:commandButton id="confirmDeleteMultiple"
value="#{messages['confirmdialog.yes']}"
onclick="blockDeleteCommand();"
onstart="PF('blockDeleteUIWidget').show();"
oncomplete="PF('blockDeleteUIWidget').hide();PF('confirmDeleteUIWidget').hide()"
actionListener="#{wishManagedBean.delete}"
process="#this"
rendered="#{wishManagedBean.renderedYesButtonDelete}"
update="a list of components to be updated"/>
<p:commandButton id="declineDeleteMultiple"
value="#{wishManagedBean.noButtonTextDelete}"
onclick="PF('confirmDeleteUIWidget').hide()"
type="button"/>
<f:facet name="message">
<p:outputPanel>
<h:outputFormat value="#{wishManagedBean.deleteMsg}" escape="false"/>
</p:outputPanel>
</f:facet>
</p:confirmDialog>
The <p:blockUI> indeed fails when the entire dialog is updated. Looks like just another bug. It works when you explicitly call the PrimeFaces.cw(...) "create widget" script of the <p:blockUI> component (exactly that script which you see in generated HTML output representation of <p:blockUI>) on complete of the dialog update.
Given those IDs,
<h:form id="formId">
<p:confirmDialog id="confirmDialogId">
<p:blockUI id="blockId" ... />
<p:commandButton id="confirmButtonId" ... />
The following oncomplete should do it:
<p:commandButton update="confirmDialogId"
oncomplete="PrimeFaces.cw('BlockUI','blockUI',{id:'formId:blockId',block:'formId:confirmId'});PF('confirmDialogId').show()" />
That explains why the <p:remoteCommand> trick works as it under the covers basically re-generates the <p:blockUI> component along with that PrimeFaces.cw(...) call, although it fires an unnecessary ajax request. It might be worth reporting an issue to PrimeFaces guys, telling that PrimeFaces.cw(...) of <p:blockUI> isn't properly executed when the confirm dialog widget is updated.
Another workaround would be to explicitly ajax-update only the parts you'd like to update instead of the entire dialog. That works for me. The header and the message attributes of the <p:confirmDialog> (and those of many other PrimeFaces components) supports being defined via <f:facet> on the attribute name. This allows you to wrap it in a <h:outputText> (or <h:panelGroup>) so that you can just update it individually. This way you don't need to update the entire dialog and the block UI keeps working as intented.
<p:confirmDialog ...>
<f:facet name="header">
<h:outputText id="confirmDeleteDialogHeader" value="#{bean.header}" />
</f:facet>
<f:facet name="message">
<h:outputText id="confirmDeleteDialogMessage" value="#{bean.message}" />
</f:facet>
<h:panelGroup id="confirmDeleteDialogContent">
<p:blockUI ... />
<p:commandButton ... />
<p:commandButton ... />
</h:panelGroup>
</p:confirmDialog>
<p:commandButton ...
update="confirmDeleteDialogHeader confirmDeleteDialogMessage confirmDeleteDialogContent"
oncomplete="PF('confirmDelete').show()" />
This requires the <p/pe:blockUI> to be updated, when the <p:commandButton> displayed on the confirm dialog is clicked.
The <p:blockUI> can be updated onclick using the <p:remoteCommand> (onstart also works).
The code goes here.
<p:confirmDialog id="confirmDeleteDialog" widgetVar="confirmDelete" message="Message" closeOnEscape="true" appendTo="#(body)" closable="true">
<p:blockUI id="blockConfirm" block="confirm" widgetVar="blockUI"/>
<p:remoteCommand name="confirmCommand" update="blockConfirm"/>
<!--Add PF('confirmDelete').hide() to oncomplete to dismiss the dialog, when this button is clicked.-->
<p:commandButton id="confirm" value="Yes" onclick="confirmCommand();" onstart="PF('blockUI').show()" oncomplete="PF('blockUI').hide()"/>
<p:commandButton id="decline" value="No" onclick="PF('confirmDelete').hide()" type="button" />
</p:confirmDialog>
<p:commandButton oncomplete="PF('confirmDelete').show()" update="confirmDeleteDialog" value="Submit"/>
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.
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;
}