Why are fields reset after ajax update with Primefaces - ajax

On a form I have some personal information (name, address etc.) and a changeListener which updates the salutation and letter salutation according to the gender and last name. If the underlying entity was already stored in the database it works fine. If I'm entering data for a new (not saved) entry the form gets reset after the listener has been called. All data entered is lost, only the salutation, lettersalutation which I modify in the listener and gender, name which I use and attached a ajax call on are kept.
This is a part of the form:
<h:form id="person">
<p:panel header="#{msg['prs']}">
<h:panelGrid columns="6" cellpadding="4">
<h:outputText value="#{msg['prs.salutation']}"/>
<p:inputText value="#{personBean.selectedPerson.salutation}"/>
<h:outputText value="#{msg['prs.lettersalutation']}"/>
<p:inputText value="#{personBean.selectedPerson.letterSalutation}"/>
<p:spacer/><p:spacer/>
<h:outputText value="#{msg['prs.name']}: "/>
<p:inputText value="#{personBean.selectedPerson.name}">
<p:ajax event="change" update="person"
listener="#{personBean.selectedPerson.updateSalutation}" />
</p:inputText>
<h:outputText value="#{msg['prs.surname']}: "/>
<p:inputText value="#{personBean.selectedPerson.surname}"/>
<h:outputText value="#{msg['prs.gender']}: "/>
<p:selectOneMenu value="#{personBean.selectedPerson.gender}">
<f:selectItems value="#{enumHelper.getEnum('Gender')}"/>
<p:ajax event="change" update="person"
listener="#{personBean.selectedPerson.updateSalutation}" />
</p:selectOneMenu>
</p:panel>
</h:form>
In the code I do then the updates.
public void updateSalutation() {
// simplified
letterSalutation = "...";
salutation = "...";
// outputs for debug
System.out.println(this.getName()); // --> not null
System.out.println(this.getSurname()); // --> null
}
Already here in this call surname, which is not attached to a ajax call is null even though data was entered there. The same is true for all the other fields. In my application I'm using Primefaces, JavaEE 1.6 with Wildfly.
What is the reason for that behavior? Is there anything I can change on my calls to prevent this?

Why are fields reset after ajax update with Primefaces
This problem has 2 possible causes depending on the concrete functional requirement:
It's because you didn't tell JSF to process the desired input values.
Or, it's because you told JSF to also update the non-desired input values.
The solution depends on the cause:
Add process="person" (or process="#form") to <p:ajax> to process the whole form.
Or, edit update="person" to specify only the components which really need to be updated.
Given your complaint in the end of the question, I believe you're looking for #1.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes

My solution:
Include the content that I want to update in a
<p:panel id="toUpdate">
and make a
update="toUpdate"

Related

How to pass a parameter in p:ajax when we used it with p:inputText?

I need to pass a parameter in my p:ajax method . there is a <p:inputText> and when I finish typing my input Box have to update my p:ajax method. But i am not able to send the parameter in my method.
My jsf page is :
<h:outputText value="#{msg['elicense.contractorFormRenewal.personal.registrationNo']}"/>
<p:inputText id="registrationNo" value="#{renewalContractorBean.registrationNo}" required="false" label="Registration No">
<p:ajaxlistener="#{renewalContractorBean.readLicenseDetailsById(renewalContractorBean.registrationNo)}/>
</p:inputText>
and my method in bean is
public void readLicenseDetailsById(String id) {
FirmOrCompany firmOrCompany = contractorRenewableService.readLicenseDetailsById(id);
this.setLicenseName(firmOrCompany.getLicensePersonName());
this.setClassofLicense(firmOrCompany.getLicenseAppliedFor());
}
There is no <p:ajaxListener>, i don't know if you missed your code or the question.
Considering you made a mistake in the question, your method should work fine, you just forgot to set the event=blur in <p:ajax>, so it get called once you leave the inputTextBox(means that the user already done typing)
<p:inputText id="registrationNo" value="#{renewalContractorBean.registrationNo}" required="false" label="Registration No">
<p:ajax event="blur" listener="#{renewalContractorBean.readLicenseDetailsById()}/>
</p:inputText>
Check that if you want to update another component, based on the changes you made in your bean, you must specify the id of that component in <p:ajax>, <p:ajax event="blur" update"IdOfTheComponent" ....>
Also, you don't have to pass properties which is already in your bean as a parameter, you can just get it in your bean.
Finally, in renewalContractorBean:
public void readLicenseDetailsById()
{
String id = this.registrationNo;
FirmOrCompany firmOrCompany= contractorRenewableService.readLicenseDetailsById(id);
this.setLicenseName(firmOrCompany.getLicensePersonName());
this.setClassofLicense(firmOrCompany.getLicenseAppliedFor());
}
Hi did you tryupdate="tableid" ? When I delete from a list which in p:dataTable, JSF can update this dataTable I hope this will be helpful.
Here is my code to update my p:datatable
<p:dataTable id="tbl" value="#{borrowerBean.borrowers}" var="bor">
<p:column>
<f:facet name="header">
<h:outputLabel>ID: </h:outputLabel>
</f:facet>
<h:outputLabel value="#{bor.id}"/>
</p:column>
.
.
.
<p:commandButton value="Delete" action="#{user.deleteBorrower(bor.id)}" update="tbl"/>
</p:column>
</p:dataTable>

Dynamic disable validator when click checkbox

I got one number validator and one checkbox in my jsf. When a checkbox is selected then the number validator will check validation. When checkbox is unselected, the validation will skip it.
Please see my code
<h:outputText value="#{trancheResources.label_enable}:" />
<p:selectBooleanCheckbox id="enableCheckBox" itemLabel="#{trancheResources.label_yes}" value="#{trancheBean.enableCheck}" disabled="#{trancheBean.readonly}">
</p:selectBooleanCheckbox>
<p:outputLabel for="acceptableMinVal" value="#{trancheResources.label_acceptableMinVal}:" />
<pe:inputNumber id="acceptableMinVal" value="#{trancheBean.trancheValidation.podMin}" disabled="#{trancheBean.readonly}" maxValue="999"
required="#{trancheBean.requiredIfEnableCheck}" requiredMessage="#{trancheResources.label_acceptableMinVal} is required.">
<f:validateDoubleRange disabled="#{trancheBean.cValidation}" minimum="1.00" />
</pe:inputNumber>
<p:outputLabel for="acceptableMaxVal" value="#{trancheResources.label_acceptableMaxVal}:" />
<pe:inputNumber id="acceptableMaxVal" value="#{trancheBean.trancheValidation.podMax}" disabled="#{trancheBean.readonly}" maxValue="999"
required="#{trancheBean.requiredIfEnableCheck}" requiredMessage="#{trancheResources.label_acceptableMaxVal} is required.">
<p:ajax event="keyup" listener="#{trancheBean.acceptableMaxValOnkeyup}" ></p:ajax>
</pe:inputNumber>
<p:outputLabel for="exceptionMinVal" value="#{trancheResources.label_exceptionMinVal}:" />
<pe:inputNumber id="exceptionMinVal" value="#{trancheBean.trancheValidation.podExceptionMin}" disabled="#{trancheBean.readonly}" maxValue="999"/>
<p:outputLabel for="exceptionMaxVal" value="#{trancheResources.label_exceptionMaxVal}:" />
<pe:inputNumber id="exceptionMaxVal" value="#{trancheBean.trancheValidation.podExceptionMax}" disabled="#{trancheBean.readonly}" maxValue="999"/>
Please guide me to a solution. I have no idea on how to solve this.
I'll provide you with this sample answer and you can use it to apply it to yours. This approach is based on Pankaj Kathiriya's comment since that seems to be what you want to do.
In the sample code below, you have two <h:inputText> (substitute this component with yours <pe:inputNumber>). Their rendered attribute value will change every time you check/uncheck the <p:selectBooleanCheckBox>. When rendered evaluates to true, the <h:inputText> with validation will appear, the one without validation disappears (and vice versa).
The <selectBooleanCheckBox> will fire a ValueChangeEvent every time you check/uncheck it. You also need to make sure to set immediate to true so that it can be processed first (one phase before). Then call renderResponse in your listener to skip the remaining life cycles. Validation will kick in for the <h:inputText> with validation if you don't and you will see a validation error message when the switch occurs. Finally, for the <h:selectBooleanCheckBox>, you want to submit the form when the selection/deselection occurs. This can be done with javascript by setting its onchange attribute to submit() (e.g. onchange = "submit()"). Try to run the code so this could all make sense.
Again, keep in mind this is just a sample to help guide you to your solution.
public class SampleBean {
private boolean renderValidatedForm;
private String firstInput;
private String secondInput;
//Constructor ommitted
//Setters and getters ommitted
public void toggleRender(ValueChangeEvent e) {
boolean valueCheck = (Boolean) e.getNewValue();
renderValidatedForm = valueCheck;
FacesContext.getCurrentInstance().renderResponse();
}
}
The xhtml
<h:form>
<h:panelGrid>
<h:panelGroup>
<h:outputLabel for="enableCheckBox" value="Check to view form with validation"/>
<p:selectBooleanCheckbox id="enableCheckBox" value="#{sampleBean.renderValidatedForm}"
onchange="submit()"
valueChangeListener="#{sampleBean.toggleRender}"
immediate="true"/>
</h:panelGroup>
<h:panelGroup>
<h:outputLabel for="withValidation" value="Form with validation"
rendered="#{sampleBean.renderValidatedForm}"/>
<h:inputText id="withValidation" value="#{sampleBean.firstInput}"
required="true" rendered="#{sampleBean.renderValidatedForm}"/>
<h:message for="withValidation"/>
</h:panelGroup>
<h:panelGroup>
<h:outputLabel for="noValidation" value="Form without validation"
rendered="#{!sampleBean.renderValidatedForm}"/>
<h:inputText id="noValidation" value="#{sampleBean.secondInput}"
rendered="#{!sampleBean.renderValidatedForm}"/>
</h:panelGroup>
</h:panelGrid>
<h:commandButton value="Submit"/>
</h:form>

JSF Ajax reset previously rendered input component values?

I have a small (but vital) problem with JSF and ajax. The form is here:
<h:form>
<h:panelGrid id="pg1" columns="2">
<h:outputText value="Type: "/>
<h:selectOneMenu id="selectOne" value="#{personBean.type}">
<f:selectItems value="#{listBean.personTypes}"/>
<f:ajax event="valueChange" render="pg2"/>
</h:selectOneMenu>
</h:panelGrid>
<h:panelGrid id="pg2" columns="2">
<h:outputText value="Really bad?" rendered="#{personBean.type=='BAD'}"/>
<h:selectBooleanCheckbox id="checkbox" value="#{personBean.reallyBad}" rendered="#{personBean.type=='BAD'}">
<f:ajax event="click"/>
</h:selectBooleanCheckbox>
</h:panelGrid>
<h:commandButton value="Ajax Submit" action="#{personBean.printValues}">
<f:ajax execute="#form"/>
</h:commandButton>
</h:form>
The PersonBean is a simple bean with an enum PersonType that has two values: NICE, BAD and a Boolean called reallyBad. The ListBean returns the enum values in a list to populate the selectOneMenu.
Basically when I select BAD the panel for the boolean checkbox is rendered where I can tick it to say a person is reallyBad. I can then submit the form if I wish. The problem is when I tick the checkbox and then select NICE again, the checkbox is still ticked even though it is not rendered. So when I submit my form the person can be NICE and reallyBad, which doesn't make sense.
Rather than having to select BAD again to uncheck the box, is their a way that I can reset the checkbox and its input value to false when NICE is selected? I'm a bit of a noob to ajax with JSF! Thanks.
ps. I am printing the values of the two inputs on submit with the commandButtons action to verify the results...
You need to manually clear the checkbox when you change the menu.
<f:ajax listener="#{personBean.setReallyBad(false)}" render="pg2" />
By the way, the both <f:ajax event> values as you've in your code are the default values already. Just omit them.

JSF 2 ProcessValidationPhase Fails Due to Uninitialized Managed Bean Property

I am looking for best-practice guidance on how to implement the following. I am using JSF2, Spring 3, PrimeFaces 3.3, MyBatis.
REQUIREMENT:
I have a data entry screen with input fields linked to VO object which is a property on the managed bean. The user can either create a new record, or search for existing records to edit.
When the edit an existing record option is selected, a dialog box appears where the user is able to search and retrieve a list of potential records to select from.
They are only able to select one record to edit at a time. Once they have made their selection, the dialog box closes, and the VO object is populated with the selected data ready for the user to edit.
PROBLEM:
When the search form is submitted to retrieve a list of potential records for editing, the VO object has not yet been initialised and causes the ProcessValidationPhase to fail the process with a "Target Unreachable".
What is the best way to implement this scenario? Should the VO object be initialised with blank values in the managed bean? Or should there be an initialise method on the VO object that is called during the initialisation of the managed bean?
DataEntry.XHTML
The main data entry fields:
<p:panelGrid id="dataEntry">
<p:row>
<p:column style="width:200px;">
<h:outputLabel value="Field 1:"/></p:column>
<p:column>
<p:inputText value="#{managedBean.dataEntryVo.field1}"
style="width:50px;"
disabled="true"/>
</p:column>
</p:row>
<p:row>
<p:column>
<h:outputLabel value="Field 2:"/>
</p:column>
<p:column>
<p:inputText value="#{managedBean.dataEntryVo.field2}"
style="width:50px;"
disabled="true"/>
</p:column>
</p:row>
</p:panelGrid>
The command button on the dialog box used to retrieve a list of possible records for selection to edit:
<p:commandButton id="retrieveDataCb"
value="Retrieve"
actionListener="#{managedBean.retrieveDataEntryList}"
update=":dataEntryForm:retrievedList">
</p:commandButton>
Many thanks
Initialising the search criterion to a dummy object will definitely work. Not very neat but it works. On the other hand, you could try using a data container component like a <p:dataGrid/> or <p:dataTable/>. There is a var attribute that will let you get away with null references like the case that you are trying to achieve. The var attribute compensates for empty datasets. That being said, you can now have a List<DataEntryVo> in your backing bean and then in your view:
<p:dataGrid id="dataEntry" value="#{managedBean.theVoList}" var="vo">
<p:panel>
<p:panelGrid>
<p:column style="width:200px;">
<h:outputLabel value="Field 1:"/>
</p:column>
<p:column>
<p:inputText value="#{vo.field1}" style="width:50px;" disabled"true"/>
</p:column>
<p:row>
<p:column>
<h:outputLabel value="Field 2:"/>
</p:column>
<p:column>
<p:inputText value="#{vo.field2}" style="width:50px;" disabled="true"/>
</p:column>
</p:row>
</p:panelGrid>
</p:panel>
</p:dataGrid>
Another alternative, you could avoid binding the input fields to an object in your managed bean altogether, instead binding the input fields to the managed bean directly as in <p:inputText binding="#{vo.field1Input}" style="width:50px;" disabled="true"/> and in your backing bean you will have UIcomponent field1Input = new HtmlInputText(); (or whatever the class is for primefaces and then call field1Input.getValue() or field1Input.setValue() according to your needs. It's also a good idea to make your bean a ViewScoped bean to avoid unnecessary trouble getting this solution to work.

How to let validation depend on the pressed button?

I have created form and I want to show previous existing items on a table while a new one is creating. I'd like to show matching items as form is filling up. But when I try to filter the list without having the form completed, the validation messages appear and the table doesn't get updated.
Don't know if it's possible, but what I want to do something like this:
<h:form id="form">
<h:outputText value="Name: "/>
<p:inputText value="#{itemsBean.name}" id="name" required="true"/>
<br/>
<h:outputText value="Description: "/>
<p:inputText value="#{itemsBean.description}" id="description" required="true"/>
<p:commandButton value="Save" update="form" actionListener="#{itemsBean.save}"/> //validate and save
<p:commandButton value="Filter" update="form" actionListener="#{itemsBean.updateItemsList}"/> //don't validate, and update the table.
<p:dataTable id="list" value="#{itemsBean.itemsList}" var="item">
<p:column>
<h:outputText value="#{item.name}"/>
</p:column>
<p:column>
<h:outputText value="#{item.description}"/>
</p:column>
</p:dataTable>
</h:form>
I'm very new to JSF.
I understand that you want to filter based on the name input field. The <p:commandButton> sends by default an ajax request and has a process attribute wherein you can specify which components you'd like to process during the submit. In your particular case, you should then process only the name input field and the current button (so that its action will be invoked).
<p:commandButton process="#this name" ... />
The process attribute can take a space separated collection of (relative) client IDs of the components, wherein #this refers to the current component. It defaults in case of <p:commandButton> to #form (which covers all input fields of the current form and the pressed button), that's why they were all been validated in your initial attempt. In the above example, all other input fields won't be processed (and thus also not validated).
If you however intend to skip the required validation for all fields whenever the button in question is been pressed, so that you can eventually process multiple fields which doesn't necessarily need to be all filled in, then you need to make the required="true" a conditional instead which checks if the button is been pressed or not. For example, let it evaluate true only when the save button has been pressed:
<p:inputText ... required="#{not empty param[save.clientId]}" />
...
<p:inputText ... required="#{not empty param[save.clientId]}" />
...
<p:commandButton binding="#{save}" value="Save" ... />
This way it won't be validated as required="true" when a different button is pressed. The trick in the above example is that the name of the pressed button (which is essentially the client ID) is been sent as request parameter and that you could just check its presence in the request parameter map.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
I Have tested this with non-ajax submits:
<p:inputText ... required="#{not empty param.includeInSave1}" />
...
<p:inputText ... required="true" />
...
<p:commandButton value="Save1" ajax="false">
<f:param name="includeInSave1" value="true" />
</p:commandButton>
<p:commandButton value="Save2" ajax="false" />
The first input is required validated only on Save1 button submit.
Additionally to the BalusC answer (very useful and complete) I want to add that when you use a <h:commandButton /> it will validate (required, custom validations) all the fields in the <h:form /> where the command button is located, therefore when you need to use more than one command button you could consider that it is a good practice to use different <h:form /> to different responsibilities to avoid unexpected behavior in submit actions of the command buttons.
It is well explained in a BalusC answer: Multiple h:form in a JSF Page
If your form has validations and you do not update the <h:form /> or you do not show messages, you could get a headache thinking that the <h:commandButton /> is not firing your action, but likely is a validation problem that has not been shown.
Change your filter commandbutton like this to ignore validation:
<p:commandButton value="Filter" update="list" actionListener="#{itemsBean.updateItemsList}" process="#this"/>
EDIT:
The related post on SO, I think this will solve your issue too
JSF 2.0: How to skip JSR-303 bean validation?

Resources