JSF 2.0 + Ajax with PrimeFaces 3.5 not working - ajax

I am having some problems and couldn't figure them out after 3 days of search. I am using JSF + PrimeFaces 3.5 + Ajax and it is not working correctly.
Basically I have a startDate and numberOfDays attributes. I want to calculate endDate automatically using ajax when both startDate and numberOfDays are informed.
These are the problems:
It is not updating the attribute endDate. The listener is called (I've breakpointed it!) and the attribute is calculated for sure.
The listener is called just once. I can't make it run twice!
This is my xhtml page:
<div>
<h:outputLabel for="startDate">
<h:outputFormat value="startDate" />
<h:inputText id="startDate" value="#{bean.startDate}">
<f:convertDateTime type="date" pattern="MM/dd/yyyy" />
</h:inputText>
</h:outputLabel>
</div>
<div>
<h:outputLabel for="numberOfDays">
<h:outputFormat value="numberOfDays" />
<h:inputText id="numberOfDays" value="#{bean.numberOfDays}">
<p:ajax listener="#{bean.calculateEndDate}" process="startDate,numberOfDays" update="panelGroupEndDate" partialSubmit="true" />
</h:inputText>
</h:outputLabel>
</div>
<div>
<h:panelGroup id="panelGroupEndDate">
<h:outputLabel for="endDate">
<h:outputFormat value="endDate" />
<h:inputText id="endDate" value="#{bean.endDate}">
<f:convertDateTime type="date" pattern="MM/dd/yyyy" />
</h:inputText>
</h:outputLabel>
</h:panelGroup>
</div>
Here is my Managed Bean
public void calculateEndDate()
{
if(startDate != null && numberOfDays != null)
{
endDate = Util.calculateEndDate(startDate, numberOfDays);
}
else
{
endDate = null;
}
}
I have ajax codes running in different pages without a problem but all these codes are triggered by a commandButton. These same example works if I use a commandButton to trigger the listener.
Does anyone know what I am doing wrong? Thanx a lot! :)

Check this out:
<p:ajax listener="#{bean.calculateEndDate}" process="startDate,numberOfDays, #this" update="panelGroupEndDate" />
I have faced the problem that the listener method is not called, sometimes adding #this to the end of process can make it right.

Related

How to invoke calendar validator on the default value at loading time

I have this piece of code. At the moment the validation is invoked by a button. But I do also want to invoke the validation if there is a default value already present there when the page loads. How can I do that? Thanks.
// ... the calendar
<div class="formBlock">
<p class="formGroupTitle">#{msg['startEmploymentDate']}</p>
<p:message id="startDateMessage" for="startDate" />
<p:calendar id="startDate" required="true" pattern="dd.MM.yyyy"
locale="de" requiredMessage="#{nts['pleaseEnterAFutureDate']}"
mindate="#{companyJobProfileCreateStep2Bean.currentDate}"
value="#{companyJobProfileCreateStep2Bean.jobProfile.startDate}"
converterMessage="#{nts['pleaseEnterAFutureDate']}"
validator="futureDateValidator" showOn="button" navigator="true">
<p:ajax event="dateSelect" update="#(.roundedNumberRefreshable)"
listener="#{companyJobProfileCreateStep2Bean.updateSearchParameters()}" />
</p:calendar>
</div>
// ... and the button
<p:commandButton
value="#{companyJobProfileCreateStep2Bean.getJobProfile().ams ? msg['sendProposal'] : msg['accept']}"
oncomplete="if (args && !args.validationFailed) {PF('generalDetailsSlider').unselect(0);PF('paymentDetailsSlider').select(0);}"
update="#(.adtextUpdateable) #(.hasAddressAndMessageUpdateable) startDate vacancies startDateMessage vacanciesMessage #(.generalDetailsSliderHeaderUpdateable) #(.progressBarCompany)"
actionListener="#{companyJobProfileCreateStep2Bean.verifyHasAddresses()}"
process="startDate vacancies" partialSubmit="true"></p:commandButton>
I've got an idea which might work by using a remoteCommand (A little hack). Basically you will simulate what will happen when the submit button is clicked. You can decide when you want to call your function.
Hope this helps.
<p:remoteCommand name="errorSubmitButton" autoRun="false/true" global="false"
oncomplete="if (args && !args.validationFailed) {PF('generalDetailsSlider').unselect(0);PF('paymentDetailsSlider').select(0);}"
update="#(.adtextUpdateable) #(.hasAddressAndMessageUpdateable) startDate vacancies startDateMessage vacanciesMessage #(.generalDetailsSliderHeaderUpdateable) #(.progressBarCompany)"
actionListener="#{companyJobProfileCreateStep2Bean.verifyHasAddresses()}"
process="startDate vacancies" partialSubmit="true" />
<h:outputScript rendered="yourConditionWhenToExecuteScriptIfYouHaveOne">
$(document).ready(function () {
errorSubmitButton();
});
</h:outputScript>

jsf f:ajax tag corrupts request

Am using Spring with JSF
I have a view scoped bean which contains a function, the xhtml file contains a dropdown menu which on value change updates some message to the user and a button which calls the function. When I change the dropdown and click the button, the function is not called
Upon removing the tag
<f:ajax event="blur" render="type_message" />, the function is called and it worked fine
it same problem as in Primefaces Commandbutton not working after an update made by select box
#Scope("view")
#Component("propertyBean")
public class PropertyBean implements Serializable {
...
public String update() {
...
return"/page.xhtml";
}
}
xhtml
<h:selectOneMenu id="type" required="true"
requiredMessage="#{msgBean.getRequired()}"
styleClass="btn btn-white dropdown-toggle" style="width:100%"
value="#{propertyBean.property.propertyDetails.type}"
converter="#{typeConverter}">
<f:selectItem itemValue="#{null}" itemLabel="choose item"
noSelectionOption="true" />
<f:selectItems value="#{dataBean.availableTypes}"
var="typeObj" itemValue="#{typeObj}"
itemLabel="#{typeObj.type}"/>
<f:ajax event="blur" render="type_message" />
</h:selectOneMenu>
<h:message id="type_message" for="type"
infoClass="help-block" errorClass="help-block error" />
<h:commandButton id="update" value="save"
onclick="if( validate('submitForm')==true){ updateProperty();} else{ return false;}"
action="#{propertyBean.update}"
class="btn btn-green btn-lg arabic"
rendered="#{propertyBean.isNew == false}">
<f:param name="propertyId" value="#{propertyBean.property.id}">
</f:param>
</h:commandButton>
on changing <f:ajax> to <p:ajax> it worked, any explanations

p:remoteCommand only update="#all" PF5

On below code <p:remoteCommand> just update whole view when I use #all, but I've tried update #this,#form or wizardEventContainer without success. Even though #all work as I wish I would prefer just update the specific container wizardEventContainer
In the PrimeFaces website the example works using id attribute therefore I don't know why I can't get it too.
I work with PF5, JSF 2.2 and SWF 2.4. I changed JSF separator char to - instead of :
<h:form id="formEditor" styleClass="eventEditorForm" prependId="true">
<p:editor id="editorEvent" height="150" width="900" maxlength="500" onchange="writeTextonPanel()" widgetVar="editorWidget" />
<h:panelGroup layout="block" id="eventEditorButtons" styleClass="eventEditorButtons">
<h:commandButton value="#{msg['saveLayer.btn']}" actionListener="#{eventProvider.saveTextLayer()}" alt="#{msg['saveLayer.btn.alt']}" title="#{msg['saveLayer.btn.title']}" onclick="showEditor('save')">
<f:ajax execute="#form" render="-formBotones-wizardEventContainer" />
</h:commandButton>
<h:commandButton value="#{msg['omitLayer.btn']}" alt="#{msg['omitLayer.btn.alt']}" title="#{msg['omitLayer.btn.title']}" onclick="showEditor('delete')">
<f:ajax execute="#form" render="-formBotones-wizardEventContainer" />
</h:commandButton>
</h:panelGroup>
<h:inputHidden id="tempCSS" value="#{eventProvider.tempCSS}" />
<h:inputHidden id="tempHTML" value="#{eventProvider.tempHTML}" />
</h:form>
<h:form id="formBotones" prependId="true">
<p:remoteCommand name="omitTextLayer" process="#this" update="formBotones-wizardEventContainer" actionListener="#{eventProvider.omitTextLayer()}" />
<p:remoteCommand name="modifyTextLayer" actionListener="#{eventProvider.modifyTextLayer()}" />
<h:inputHidden id="tempCSSforModify" value="#{eventProvider.tempCSSModified}" />
<h:panelGroup layout="block" id="wizardEventContainer" styleClass="wizardEventContainer">
<h:inputHidden id="tempTextIdLayer" value="#{eventProvider.tempTextIdLayer}" />
</h:panelGroup>
</h:form>
JS code linked with JAVA method
function showEditor(mode){
if(mode=='save')
saveLayer();
if(mode=='delete')
deleteLayer();
if($('#eventEditorContainer').css('visibility')=="hidden"){
$('#eventEditorContainer').css('visibility','visible');
$('#formControl-textLayerBtn').prop("disabled",true);
}
else{
$('#eventEditorContainer').css('visibility','hidden');
$('#formControl-textLayerBtn').prop("disabled",false);
}
}
function deleteLayer(layer){
if(layer==null){
var idLayer='formBotones-' + $('#formBotones-tempTextIdLayer').val();
$('#' + idLayer).remove();
$('#formEditor-tempCSS').val('');
$('#formEditor-tempHTML').val('');
}
else{
var idLayer=layer.parent().attr('id');
layer.parent().remove();
$('#formBotones-tempTextIdLayer').val(idLayer.substring(idLayer.indexOf("-")+1));
$('#formEditor-tempCSS').val('');
$('#formEditor-tempHTML').val('');
}
omitTextLayer(); // p:remoteCommand function
}
P.D: I'v edited adding full code sample and js code which link to java method on p:remoteCommand
Thanks!
Update works right using IDs if p:remoteCommad if thrown from p:commandButton instead of h:commandButton.
So, code must change to
<p:commandButton value="#{msg['omitLayer.btn']}" alt="#{msg['omitLayer.btn.alt']}" title="#{msg['omitLayer.btn.title']}" onclick="showEditor('delete')" />

Open PrimeFaces Dialog located in another .xhtml file

I have a number of questions that are related to each other so the title of question may not be appropriate. Sorry for this.
I want to have a p:inputText and p:commandButton in a p:dialog such that when the user presses that button or presses enter key the value entered in the
p:inputText will be saved in the database. To do this I followed this example http://www.primefaces.org/showcase/ui/dialogForm.jsf and it worked fine when I tried it in a seperate .xhtml file in which there were no other dialogs or command buttons.
<h:body>
<h:form id="form">
<p:commandButton id="showDialogButton" type="button" value="Show" onclick="PF('dlg').show()" />
<p:dialog header="Enter FirstName" widgetVar="dlg" resizable="false">
<h:panelGrid columns="2" style="margin-bottom:10px">
<h:outputLabel for="firstname" value="Firstname:" />
<p:inputText id="firstname" value="#{subjectController.attributeValue}" />
</h:panelGrid>
<p:commandButton id="submitButton" value="Submit" update=":form:display :form:firstname" action="#{subjectController.saveUpdateSubjectAttributeValue}" oncomplete="PF('dlg').hide();"/>
<p:defaultCommand target="submitButton"></p:defaultCommand>
</p:dialog>
<p:outputPanel id="display" style="display:block;margin-top:10px;">
<h:outputText id="name" value="Hello #{subjectController.attributeValue}" rendered="#{not empty subjectController.attributeValue}"/>
</p:outputPanel>
</h:form>
</h:body>
The .xhtml file that I originally have contains a number of other dialogs and command buttons. When i used the same code in that file it does not work properly. By not working properly I mean to say that when enter key or submit button is pressed the value entered by the user is not set in the corresponding setter of the inputText in the managed bean. To call the setter before pressing the enter key or button I need to use p:ajax inside p:inputText tag. I tried to use p:ajax events such as "mouseout", "blur", "change" etc. They work for the submit button but not for the enter key. Then I tried "keypress" and "keyup" etc. They worked for both but the setter for the value in the p:inputText was called on each key press which was not desired.
My first question:
If the sample code is working fine in a separate file why doesn't it work when I have other dialogs or commandbuttons in the same file. In both the cases I am using the same managed bean. What is the difference?
Assuming that the problem may be caused using more than one dialogs in the same file, I thought of declaring these dialogs in separate files such that I have
A.xhtml , B.xhtml, C.xhtml pages which contain the actual content and whenever I need to open a dialog the required dialog is located in file such as dialog.xhtml. Being a beginner in JSF, Primefaces and Ajax I was confused about how to do this. Searching on the internet I found this post relevant PrimeFaces dialog lazy loading (dynamic="true") does not work?. But in this case, p:dialog is located on the same page but the content contained in this dialog is located in another file which is included using ui:include. I tried this but it shows the same behavior.
My Second Question:
Is there any way to programmatically open a dialog from another file e.g. if I have a p:commandButton in A.xhtml and p:dialog in the same file I can do this using
<p:commandButton id="submitButton" value="Submit" update=":form:display :form:firstname" action="#{subjectController.saveUpdateSubjectAttributeValue}" oncomplete="PF('dlg').hide();"/>
and in the corresponding subjectController I have
saveUpdateSubjectAttributeValue(){
RequestContext context = RequestContext.getCurrentInstance();
context.openDialog("openDialog");
// or
context.execute("openDialog");
}
But what if the "openDialog" is located in B.xhtml?
What I understand, I can use enclose p:dialog in a ui:composition (in B.xhtml) and and use ui:include in A.xhtml. But I am confused in how and where to call openDialog.open() or openDialog.hide()?
I've tried to replicate the behavior you posted here and I believe that the cause is probably somewhere else as mentioned by Yipitalp.
Anyway, here are the sample code I used that might do what you expect (Primefaces 4):
The Managed Bean
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import org.primefaces.context.RequestContext;
#ManagedBean
#ViewScoped
public class DialogBean implements Serializable {
private String attribute1;
private String attribute2;
private String attribute3;
private String dlg;
public void openDialog() {
RequestContext context = RequestContext.getCurrentInstance();
context.execute("PF('" + dlg + "').show()");
}
public String getAttribute1() {
return attribute1;
}
public void setAttribute1(String attribute1) {
this.attribute1 = attribute1;
}
public String getAttribute2() {
return attribute2;
}
public void setAttribute2(String attribute2) {
this.attribute2 = attribute2;
}
public String getAttribute3() {
return attribute3;
}
public void setAttribute3(String attribute3) {
this.attribute3 = attribute3;
}
public String getDlg() {
return dlg;
}
public void setDlg(String dlg) {
this.dlg = dlg;
}
}
The view
Note that I use a different form for every dialog in the view.
<h:form>
<h:panelGrid columns="2" style="margin-bottom:10px">
<h:outputLabel for="dlg" value="Dlg:" />
<p:selectOneMenu id="dlg" value="#{dialogBean.dlg}" >
<f:selectItem itemLabel="dlg1" itemValue="dlg1" />
<f:selectItem itemLabel="dlg2" itemValue="dlg2" />
<f:selectItem itemLabel="dlg3" itemValue="dlg3" />
</p:selectOneMenu>
</h:panelGrid>
<p:commandButton id="submitButton" value="Submit" action="#{dialogBean.openDialog}"/>
<p:defaultCommand target="submitButton" />
</h:form>
<p:button id="showDialogButton1" value="Show 1" onclick="PF('dlg1').show();
return false;" />
<p:button id="showDialogButton2" value="Show 2" onclick="PF('dlg2').show();
return false;" />
<p:button id="showDialogButton3" value="Show 3" onclick="PF('dlg3').show();
return false;" />
<br />
<p:dialog header="Enter FirstName" widgetVar="dlg1" resizable="false">
<h:form>
<h:panelGrid columns="2" style="margin-bottom:10px">
<h:outputLabel for="firstname" value="Firstname:" />
<p:inputText id="firstname" value="#{dialogBean.attribute1}" />
</h:panelGrid>
<p:commandButton id="submitButton" value="Submit" oncomplete="PF('dlg1').hide();"/>
<p:defaultCommand target="submitButton" />
</h:form>
</p:dialog>
<p:dialog header="Enter FirstName" widgetVar="dlg2" resizable="false">
<h:form>
<h:panelGrid columns="2" style="margin-bottom:10px">
<h:outputLabel for="firstname" value="Firstname:" />
<p:inputText id="firstname" value="#{dialogBean.attribute2}" />
</h:panelGrid>
<p:commandButton id="submitButton" value="Submit" oncomplete="PF('dlg2').hide();"/>
<p:defaultCommand target="submitButton" />
</h:form>
</p:dialog>
<p:dialog header="Enter FirstName" widgetVar="dlg3" resizable="false">
<h:form>
<h:panelGrid columns="2" style="margin-bottom:10px">
<h:outputLabel for="firstname" value="Firstname:" />
<p:inputText id="firstname" value="#{dialogBean.attribute3}" />
</h:panelGrid>
<p:commandButton id="submitButton" value="Submit" oncomplete="PF('dlg3').hide();"/>
<p:defaultCommand target="submitButton" />
</h:form>
</p:dialog>
<p:outputPanel autoUpdate="true" style="border: 1px solid black; margin-top:10px;">
Value 1:
<h:outputText id="v1" value="#{dialogBean.attribute1}" />
<br />
Value 2:
<h:outputText id="v2" value="#{dialogBean.attribute2}" />
<br />
Value 3:
<h:outputText id="v3" value="#{dialogBean.attribute3}" />
</p:outputPanel>
I hope that will give you some clue!
I was able to solve major part of my problems using DialogFramework. I have a Menu.xhtml page, it contains p:tieredMenu in p:layoutUnit with position="north" using which I select which page to open. Depending on the selection, the p:layoutUnit with position="center" includes that page using ui:include. The Menu.xhtml page contains a h:form with id="form" inside h:body and everything else is placed inside this h:form. There are a number of pages that can be included inside the <p:layoutUnit position="center"> depending upon the selection. One of them is Person.xhtml(containing everything enclosed inside a ui:composition ). It contains a p:fieldset. Inside p:fieldset there are 3 p:dataTable. Outside this p:fieldset I have placed 3 p:contextMenu one for each of those datatables. Inside one of those p:contextMenu I have placed
<p:menuitem value="Update" actionListener="#{controller.updateAttributeValue}" />
and the corresponding function contains
public void updateAttributeValue(){
System.out.println("update attribute value");
RequestContext context = RequestContext.getCurrentInstance();
context.openDialog("selectCar2");
this.attributeValue = null;
}
selectCar2.xhtml contains the following code
<h:body>
<h:form>
<h:panelGrid id="updateAttributeValuePanel" columns="2" style="margin-bottom:10px">
<h:outputLabel value="Attribute Value " />
<p:inputText id="attributeValue" value="#{controller.attributeValue}" required="true" />
</h:panelGrid>
<p:commandButton id="saveUpdateAttributeValue" value="Submit" actionListener="#{controller.saveUpdateAttributeValue}"
/>
<p:commandButton id="cancelUpdateAttributeValue" value="Cancel "
action="#{controller.cancelUpdateAttributeValue}"
/>
<p:defaultCommand target="saveUpdateAttributeValue" />
</h:form>
</h:body>
The corresponding save function is as follows
public void saveUpdateAttributeValue(){
RequestContext context = RequestContext.getCurrentInstance();
System.out.println("this.attributevalue = " + this.attributeValue);
////save value in database
this.attributeValue = null;
context.update(":form:resourceAttributeValueDataTable");
//also tried context.update("resourceAttributeValueDataTable");
context.closeDialog(this.attributeValue);
}
and
public void cancelUpdateAttributeValue(){
RequestContext context = RequestContext.getCurrentInstance();
context.closeDialog(this.attributeValue);
System.out.println("cancel update attribute value");
this.attributeValue = null;
System.out.println("this.attributevalue = " + this.attributeValue);
}
The dialog opens and the value is successfully saved in the database. The only problem now is that the corresponding datatable is not updated and I need to refresh the page to see the updated value. previously my dialog was also in the same page outside the p:fieldset and I was not using h:form inside dialog so I was updating the datatable as
<p:commandButton id="saveUpdateAttributeValue" value="Submit" actionListener="#{controller.saveUpdateAttributeValue}"
update = ":form:attributeValueDataTable "/>
But now they are in two different files and two different forms so I am not sure how to update in this case? I have tried to use
context.update(":form:resourceAttributeValueDataTable");
//or
context.update("resourceAttributeValueDataTable");
but the datatable is not updated. Any help will be highly appreciated.

Passing <p:inputText> values to Bean using ajax

I am having the h:inputText which having a text and by ajax request how can i send it's values to bean class and the values will be validated in further action begin at bean class ..
view page code is
<h:form>
<p:panel id="panel" header="Login Panel" style="margin:0 auto;width:350px;margin-top:15%;">
<p:panelGrid columns="3" id="pgrid1" styleClass="theme" >
<p:outputLabel value="User Name:" />
<p:inputText id="name" value="#{loginBean.name}" required="true" requiredMessage="Name is required">
<f:ajax event="blur" render="label" listener="loginBean.validateName" ></f:ajax>
<!--Here the ajax event working properly but how can i get the inputText value when ajax event is invoked-->
</p:inputText>
<p:message for="name" style="color: red;" />
</p:panelGrid>
<p:commandButton type="Submit" value="Submit" action="#{loginBean.validate}" update="pgrid1" />
</p:panel>
My Bean class Code is :
public void validateName(AjaxBehaviorEvent e)
{
//Here i need inputText value..how can i handle this task..!!
}
JSF has already set the #{loginBean.name} value at that moment. Just access it directly.
public void validateName(AjaxBehaviorEvent e)
{
System.out.println(name); // Look, JSF has already set it.
// ...
}
You've by the way an EL syntax error in <f:ajax listener> which causes the listener method never to be invoked, but I'll bet it to be just carelessness during preparing the question as you mentioned that it is "working properly". In the future questions, please edit code in the real development environment and copypaste real working code instead of blindly editing the code in the question editor.

Resources