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

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;
}

Related

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!!

primefaces schedule with parameter in jsf

Hello I am here to ask your help following a difficult i meet in my project .Your different point of vue are welcome.
I am using primefaces Schedule to perform a given task but I don't know how
I can pass a parameter to my backing bean.I would like to use this parameter in backing bean when a schedule event triggered like SelectEvent or dateSelect . For example if I have a parameter personeID I would pass this
parameter to the bean so that when actionListener will activate this
setting can be initialized in the bean so that I can use.
that my code
<p:schedule id="schedule" value="#{inscrireAgendaBean.eventModel}" widgetVar="myschedule" process="#form" axisFormat="HH:mm" columnFormat="dddd D/MM" firstHour="08" locale="fr" timeZone="GMT+1" timeFormat="HH:mm">
<p:ajax event="dateSelect" listener="#{inscrireAgendaBean.onDateSelect}" update="eventDetails" oncomplete="PF('eventDialog').show();" />
<p:ajax event="eventSelect" listener="#{inscrireAgendaBean.onEventSelect}" update="eventDetails" oncomplete="PF('eventDialog').show();" />
</p:schedule>
I just want to know if there is a possibility to add a parameter to my bean when eventSelect or dateSelect triggered
Thank you !!!
I understand from your question that you want to triger a listener when you select an event, so you have to add a p:ajax with a eventSelect event :
<p:schedule id="scheduleLocale" value="#{managedBean.schedule}" draggable="false" resizable="false" axisFormat="HH:mm" columnFormat="dddd D/MM" firstHour="08" locale="fr" timeZone="GMT+1" timeFormat="HH:mm" >
<p:ajax event="eventSelect" listener="#{managedBean.onEventSelect}" update="eventDetails" oncomplete="PF('eventDialog').show();" />
</p:schedule>
and on you managedBean the onEventSelect method will be as follows:
public void onEventSelect(SelectEvent selectEvent) {
event = (ScheduleEvent) selectEvent.getObject();
}
so getObject() will allow you to retrieve informations like personeID, and depends if you actually put personelID when you first created the event with event = new DefaultScheduleEvent()
to add an event by selecting a date on a schedule, you use p:ajax with dateSelect event:
<p:ajax event="dateSelect" listener="#{managedBean.onDateSelect}" update="eventDetails" oncomplete="PF('eventDialog').show();" />
this will show up a dialog, you can put any information you want to add to the event, the user will enter it, so no need to pass any parameters.

Blocking a p:commandButton displayed on a p:confirmDialog in addition to displaying a dynamic message on the dialog

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"/>

Field required depending on the value of an other field with JSF2 / PF4 [duplicate]

This question already has an answer here:
Conditionally make inputs required depending on checkbox value
(1 answer)
Closed 8 years ago.
I am using JSF 2.2 with Primefaces 4 on a Tomcat 7.
I have a form in which certains fields are required depending on the value of a checkbox. So In the example below, the fields in the fieldset are required only if the checkbox is checked (which is, by default) :
<h:form id="formId">
...
<p:selectBooleanCheckbox id="fieldId1" value="#{myBean.firm}">
<p:ajax event="change" process="#this :formId:fieldsetId" update="#this :formId:fieldsetId"/>
</p:selectBooleanCheckbox>
...
<p:fieldset id="fieldsetId">
<p:inputText id="field2" value="#{myBean.field2Value}" required="#{myBean.firm}"/>
<p:inputText id="field3" value="#{myBean.field3Value}" required="#{myBean.firm}"/>
</p:fieldset>
</h:form>
My problem is that the ajax request passes through the validation, so when i unchecked the checkbox, the validation fails on the inputFields if they are not filled, and the model is not updated.
So my attribute firm is still set to true in myBean and my inputText fields are still required.
At first I forgot to process the fieldset
<p:ajax event="change" process="#this" update="#this :formId:fieldsetId"/>
This worked, or I though, but as the field are not processed, if I filled some fields before unchecking the box, all the data were lost. Setting immediate="true" won't work either in that case.
It seems to me to be a very simple and common usecase, and I can't believe there is not a solution.
Thanks
Hy,
<h:form id="formId">
...
<p:selectBooleanCheckbox id="fieldId1" value="#{myBean.firm}">
<f:ajax listener="#{bean.checkBoxListener}" immediate="true" update=":formId:fieldsetId" />
</p:selectBooleanCheckbox>
...
<p:fieldset id="fieldsetId">
<p:inputText id="field2" value="#{myBean.field2Value}" required="#{myBean.firm}"/>
<p:inputText id="field3" value="#{myBean.field3Value}" required="#{myBean.firm}"/>
</p:fieldset>
</h:form>
in the bean
public void checkBoxListener(ValueChangeEvent event) {
this.firm = (Boolean) ((UIInput) event.getComponent()).getValue();
}

how to rerender a4j:commandLink after the action has been completed

i have a very simple code here:
<a4j:commandLink action="#{ticketAboxEventHelper.removeAboxTicket(ticketAbox)}"
onclick="if(!confirm('Are you sure ... ?')) return false;"
reRender="aboxlistpanel">
<h:graphicImage alt="Delete" url="../../img/dialog-error-5.png" title="Delete" />
<a4j:support event="oncomplete"
action="#{editTicketNewAction.testRerender()}"
reRender="aboxlistpanel"
/>
</a4j:commandLink>
When the link clicked the system must
ask if the user is confirmed
do the action
rerender the aboxlistpanel
Now my problem is the rerendering is hapenning before the action is getting finished. any idea how it can be done in the right way?
Your action methods is not valid for JSF 1.2 and you don't need the <a4j:support>. Since you want to pass a parameter, you should use <f:attribute /> and actionListener :
<a4j:commandLink actionListener="#{ticketAboxEventHelper.removeAboxTicket}" onclick="if(!confirm('Are you sure ... ?')) return false;" reRender="aboxlistpanel">
<h:graphicImage alt="Delete" url="../../img/dialog-error-5.png" title="Delete" />
<f:attribute name="ticket" value="#{ticketAbox}" />
</a4j:commandLink>
Your bean method will look like this :
public void removeAboxTicket(ActionEvent event)
{
TicketAbox ticket = (TicketAbox)event.getComponent().getAttributes().get("ticket");
// Your business logic
}
More info :
How to pass parameters in method expression JSF 2.0
Solved. I wrapped the offending JSF code in a and everything began working as expected. related to answer <a4j:commandLink> Not Rerendering. i solved it first and then found out someone else solved it in the same way. hmmm....

Resources