Primefaces editable dataTable and hibernate validator - jsf

I have an editable dataTable in PrimeFaces and am using the Hibernate Validator for bean validation. This works fine with a <p:inputText /> element. Now I want to have validation on a dataTable which is editable.
This is what is happening:
If I enter valid values, the page updates as expected
If I enter invalid values, when I click the little "save" check mark nothing happens - the cell remains editable, database write is not attempted, no error message is displayed.
There is an <h:messages /> tag on the page, so why doesn't an error message show up? The component appears to be aware there was a problem since the row remains in the editable state.
EDIT: I enabled logging and saw this:
21:20:43,874 FINE [javax.enterprise.resource.webcontainer.jsf.context] (http-localhost-127.0.0.1-8080-2) Adding Message[sourceId=demoTable:j_idt11:2:j_idt15,summary=Testing Hibernate Validator Error Message)
So it looks like the context is being correctly updated. It seems like I need to do something to trigger the message it render.

Use the belowfollowing statement in your jsf file and it should work:
<p:messages id="messages" showDetail="true" autoUpdate="true"
closable="true" showSummary="false"/>

Related

Update JSF messages after initial rendering via p:menuitem

Does anyone know if it's possible to update a JSF message or messages element AFTER its initial rendering via PrimeFaces' p:menuitem?
For example, I have a PrimeFaces p:menuitem I am using to open a p:dialog, and that p:dialog has a p:messages element whose message I would like to update and show the moment that the p:dialog is opened - I can't know whether there is a message I want to show or what that message should be until after the p:menuitem's action method is complete.
Unfortunately, setting the update attribute of the p:menuitem to both the id of the p:dialog and the id of the p:messages element itself does not cause the p:messages element to show its message, even though I think it should since the action method of the p:menuitem looks like it is properly adding a message to the p:messages element.
The menuitem opening the dialog:
<p:menuitem value="Show Dialog with Message" action="#{myView.prepareDialogWithMessage()}" oncomplete="PF('dialogWidget').show()" update="dialogWithMessage message" />
The dialog with the message:
<p:dialog id="dialogWithMessage" widgetVar="dialogWidget" resizable="false" dynamic="true" closable="false" showEffect="fade" hideEffect="fade">
<p:messages id="message" for="message" showDetail="true" escape="false" autoUpdate="true"/>
<div class="button-panel">
<p:commandButton value="Yes" styleClass="ui-confirmdialog-yes" action="#{myView.submitAction()}" oncomplete="PF('dialogWidget').hide();"/>
<p:commandButton value="No" styleClass="ui-confirmdialog-no" onclick="PF('dialogWidget').hide();"/>
</div>
</p:dialog>
The Java code which adds the message:
public void prepareDialogWithMessage() {
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_WARN, "Summary of message we want to show when the dialog opens", "Details of the message we want to show when the dialog opens");
FacesContext.getCurrentInstance().addMessage("message", message);
}
Short answer: It behaves exactly as expected and implemented.
Longer answer:
Having a closer look after your edited question, I noticed the dynamic="true" on the dialog. If you read the PrimeFaces docs it states (as you already found out):
dynamic: Enables lazy loading of the content with ajax.
So when you show the dialog via javascript, its content is updated... Since this content also includes the p:messages, that is also updated. In your case updated again with the messages that are generated in the ajax call of the update of the dialog... Most likely none... So the messages you added to it in the prepareDialogWithMessage() call of the menuItem are lost.
Since you already update the dialog in the call to the menuItem, the dynamic='true' is totally superfluous and it throws a spanner in the works.
<off-topic>A suggestion is to always start creating an [mcve]. Removing more and more until the behaviour of certain parts is as expected. Removing the dynamic='true' in one of the steps would have resulted in this and you'd have known a lot more. At the same time, also try debugging more. Investigating by looking at the requests and responses in the browser developer tool. You would have seen the messages getting added to the dialog and then the dialog(contents) being totally overridden. All these things are easy too (sorry, easy instead of 'not to difficult), can/will tell you a lot and helps getting to the cause of things quicker. Either directly, or by being able to ask way more specific question that is often easier to answer</off-topic>

Why does p:resetInput require properties of a managed bean to be set to null first after the form is submitted?

In a view scoped managed bean, I'm using <p:resetInput> to clear the values held by the properties in the corresponding manged bean like,
<p:commandButton value="Reset" update="panel" process="#this">
<p:resetInput target="panel" />
</p:commandButton>
This works fine.
I have a submit button <p:commandButton> which when pressed causes the submitted values to be inserted into the database, if validation succeeds.
<p:remoteCommand name="updateTable" update="dataTable"/>
<p:panel id="panel" header="New">
<p:outputLabel for="property1" value="property1"/>
<p:inputText id="property1" value="#{bean.property1}" required="true">
<f:validateLength minimum="2" maximum="100"/>
</p:inputText>
<p:message for="property1" showSummary="false"/>
<p:commandButton id="btnSubmit"
update="panel messages"
oncomplete="if(!args.validationFailed) {updateTable();}"
actionListener="#{bean.insert}"
value="Save"/>
<p:commandButton value="Reset" update="panel" process="#this">
<p:resetInput target="panel" />
</p:commandButton>
</p:panel>
The command button invokes the insert() method in the managed bean which is defined as follows.
public void insert() {
if (service.insert(property1)) {
//...Popup a success message.
reset(); //Invoke the following private method.
} else {
//...Show the cause of the failure.
}
}
private void reset() {
property1 = null; //Set this property of type String to null.
}
If this reset() method is omitted, then <p:inputText> will not be cleared as obvious but then if I press the reset button as shown in XHTML, <p:inputText> should be cleared but it doesn't.
The showcase example demonstrates exactly the same thing. Therefore, this behaviour appears to be documented but I don't understand why doesn't <p:resetInut> clear the value of property1, if the reset() method is omitted, in this case?
The <p:resetInput> does not clear the model values as you incorrectly seemed to expect. It just clears the input component's state which may be dirty after a validation error.
The concrete problem it is trying to solve is in detail described in this answer: How can I populate a text field using PrimeFaces AJAX after validation errors occur?
This is the best understood by the following use case:
You have a single view with a single datatable and a single dialog which displays the currently selected record for editing.
You open the dialog and submits its form with invalid values. The input components are marked invalid and highlighted red.
You close the dialog without fixing the errors.
Then you select same or another row for editing. The dialog shows up, but the input components are still marked invalid and highlighted red and show the old submitted value -if any- because it's still the same view state you're working with.
Putting <p:resetInput> with target on dialog's form in the "open dialog" button fixes it.
I'm not sure if your particular case is the right use case for which <p:resetInput> is the right solution. Your code is not complete and you didn't state the concrete functional requirement behind this code anywhere, but as far as I see, there are no multiple inputs/forms which need to update each other. I believe that your case would still work even if you remove <p:resetInput>. So it would be totally superflous in your context and you could just get away with clearing the model (or.. just with refreshing the page by a synchronous GET button which implicitly recreates the view).
See also:
PrimeFaces CommandButton that Doesn't Process Data
Escape a primefaces/jsf page that has required fields

How to block showing p:growl message in primefaces

I have defined a p:growl in my xhtml page like this:
<p:growl id="growl" showDetail="true" />.
When submit my form shows an error message for the required field when they are empty. And it highlights the required field with a red border.
So I need highlighting part but don't want to show p:growl. But p:growl component is used for another purpose. How can I block showing
p:growl when required field is empty?
Jens's variant make growl not to show ALL messages. Next solution works for me:
<p:growl id="growl" showDetail="true" rendered="#{not facesContext.validationFailed}"/>
If I understand your question correctly you want to show the p:growl only when there is no validation error.
To achieve this you could add a rendered attribute to the growl component:
<p:growl id="growl" showDetail="true" rendered="#{empty facesContext.messages}"/>
This will render the growl only if there is no validation error.
EDIT: I removed the not in the el.

Cannot find component with identifier in View JSF

I was trying to show messages using a p:growl like this.to be updated on the OnRowSelect Method of a Data Table lazy loading like this
<p:growl id="applyMessages" showDetail="false" global="true" /> and <p:ajax event="rowSelect" listener="#{editBean.onRowSelect}" update=":studyPlanEditForm:display applyMessages"/>
but got the error like this
Cannot find component with identifier "applyMessages" in view.
Please Help.
Check the source code of your page in browser. Then identify the p:growl markup and its generated client-id. It surely is longer than applyMessages and has a prefix similar to containerID:applyMessages. Use this id in your update attribute of the ajax call.

JSF/Richfaces/A4j ==> component/field conversion and reRendering problem

I have an input field in a JSF Page like the following (maps to BigDecimal on backing bean)
<h:inputText disabled="#{volumeBean.grossVolumeDisabled}" id="grossVolume" size="10" validateOnExit="true" value="#{volumeBean.enteredGrossVolume}" >
<a4j:support ajaxSingle="true" event="onblur" ignoreDupResponses="true" oncomplete="checkFieldValidation(this)" onsubmit="updateDirty()"/>
</h:inputText>
And an a4j:commandButton to "refresh" all the data from the database on the page:
<a4j:commandButton accesskey="T" action="#{volumeBean.revert}" button-type="ajax" disabled="#{volumeBean.revertDisabled}" id="volumeBean_reset" immediate="true" reRender="volumesTable" value="#{msg.button_RESET}"/>
Here are the steps to reproduce my problem:
And please note that the error occurs regardless of whether there is a reRender attribute set on the a4j:support
Here are the steps to reproduce - just to clarify further:
navigate to the screen where the BigDecimal input field exists
type aa into the field (should be a number but put non-numeric characters purposely)
tab off the field
notice that an error is reported 'aa' is not a valid netVolume
click on the RESET button
all of the changed fields have their original values EXCEPT those that have non-numeric data entered
unless the user manually deletes the non-numeric data in the fields or refreshes the entire screen, the "bad data" sticks
When you do a reset, you fire an Ajax request, the entire form is submitted and you get validation error again. So the field still has the old (incorrect) value.
Try adding the parameter ajaxSingle="true" to the button. I've found that immediate="true" is not adequate for bypassing validation on ajax components.

Resources