I am tying to use the primefaces client side validation framework. Most of it is working correctly, but for some reason the validatorMessage doesn't display in my growl. When I just have the server side validation it appears fine. I have added a standard message and this also appears fine, it just won't appear in the growl.
My growl is defined as:
<p:growl id="errorMsg" showDetail="true" sticky="true" autoUpdate="true" widgetVar="growlErrorMsg" />
A snippet of my xhtml is:-
<div class="field">
<p:outputLabel for="Amt1"
rendered="#{MyWebPage.amt1.isRendered()}"
value="Amt: "
binding="#{MyWebPage.amt1Prompt}" >
<span class="required">*</span>
</p:outputLabel>
<p:inputText id="Amt1" maxlength="10"
validatorMessage="Input must match this pattern: -ZZZZZZZZZ9"
value="#{flowScope.amt}"
binding="#{MyWebPage.amt1}"
disabled="#{MyWebPage.isDisabledAmt1('')}"
styleClass = "numeric" >
<f:converter converterId="zero" />
<f:validateRegex pattern="^-?([0-9]{1,10})$" />
<p:clientValidator />
</p:inputText>
<p:message for="Amt1" />
</div>
The code above includes the <p:message> which displays successfully. Without this, the field error is still highlighted but no message appears.
I am using Primefaces 6.0, JSF 2.1.13 (Mojarra), and running on Tomcat 8.5.4.
Any guidance would be much appreciated.
Related
I have a hidden <p:fileUpload> which is opened via <h:outputLabel>.
<p:messages id="message" autoUpdate="true" />
<h:form id="form">
<p:fileUpload id="file-input" auto="true"
allowTypes="/(\.|\/)(gif|jpe?g|png)$/" sizeLimit="10"
invalidSizeMessage="wrong size" fileUploadListener="#{bean.image}"
update="#form message" style="display: none;"
invalidFileMessage="wrong file" />
<h:outputLabel for="file-input_input">
<h:graphicImage name="images/dummy.jpg" />
</h:outputLabel>
<h:outputText value="#{bean.file.fileName}" />
<br />
<h:outputText value="#{bean.file.size}" />
</h:form>
Unfortunately, no messages are displayed after validation failed (e.g invalid size or invalid file). Those messages are displayed inside the <p:fileUpload> content box instead of in <p:messages>.
How can I display those messages inside <p:messages> instead of inside <p:fileUpload>?
The validation is performed fully client side without hitting the server. So you can't control this from server side on.
The message container of the <p:fileUpload> is available via messageContainer property of the widget variable. Simple let jQuery move it into the <p:messages> when clicking the label:
<p:messages id="messages" ... />
<h:form>
<p:fileUpload id="file-input" widgetVar="file-input" ...
styleClass="ui-helper-hidden" />
...
<h:outputLabel for="file-input_input" ...
onclick="PF('file-input').messageContainer.appendTo($('#messages'));" />
</h:form>
(I only renamed <p:message id> to be more sensible, and used a PrimeFaces specific class to hide it instead of an inline style)
The onstart and oncomplete attributes of <p:fileUpload> weren't usable as they are only executed when the client side validation has passed and the file upload request is actually sent.
I have the maven dependency for omnifaces for version 1.11 (as my target is JDK 1.6). Richfaces 4.5.6 final, myfaces 2.2.8. And, against a viewscoped bean I have got this xhtml:
<ui:define name="content">
<f:loadBundle basename="au.com.erb.facility.ui.facility"
var="property" />
<o:highlight styleClass="error" />
<h:panelGrid columns="2">
<rich:validator event="change">
<o:outputLabel value="#{property.absClientNumber}" for="input1" />
<h:inputText id="input1"
value="#{facilityBean.facilityForEdit.alternateKey.absClientNumber}"
label="ABS Client Number" />
<o:outputLabel value="#{property.facilityid}" />
<h:inputText
value="#{facilityBean.facilityForEdit.alternateKey.facilityId}"
label="Facility Id" />
<h:outputLabel value="#{property.rfsAccountGroup}" />
<h:inputText value="#{facilityBean.facilityForEdit.rfsAccountGroup}"
label="RFS Account Group" />
<h:outputLabel value="#{property.rfsAcctCustomerNumber}" />
<h:inputText
value="#{facilityBean.facilityForEdit.rfsAcctCustomerNumber}"
label="RFS Account Customer Number" />
<h:outputLabel value="#{property.rfsAcctLedger}" />
<h:inputText value="#{facilityBean.facilityForEdit.rfsAcctLedger}"
label="RFS Account Ledger" />
</rich:validator>
</h:panelGrid>
</ui:define>
<!-- Buttons that performs actions on a selected record -->
<!-- or navigate to a relevant screen -->
<ui:define name="buttons">
<h:commandButton id="submitButton" value="#{property.submitLabel}"
action="#{facilityBean.save}" styleClass="wideButton"
onclick="#{rich:component('progressWaitModalPanel')}.show()" />
<h:commandButton id="closeButton" value="#{property.closeLabel}"
action="#{facilityBean.close}" styleClass="wideButton"
immediate="true" />
<rich:popupPanel id="progressWaitModalPanel" modal="true">
<f:facet name="header">
<h:outputText value="Processing your request ...." />
</f:facet>
<h:panelGrid columns="1"
style="width: 100%; border-width: 0px; text-align: center;">
<h:outputText value="Please wait..." styleClass="dataValueStyle" />
</h:panelGrid>
</rich:popupPanel>
</ui:define>
The result is nothing. No higlight. No clue what's going on. Have I missed any installation step? I have the css and xmlnamespace in place. Anything else?
I tried to add required="true" as it was shown in the example, but that did not work either. Not sure whether it is due to richfaces bean validation issue.
The <o:highlight> works server side, based on a.o. UIInput#isValid() in JSF component tree. The <rich:validator> works client side and doesn't manipulate JSF component tree.
This indeed doesn't go well together.
I briefly looked into the HTML/JS code of the <rich:validator> showcase and it appears that they don't add a marker style class to the input elements when it's invalid (e.g. PrimeFaces does), so it's going to be hard to write a workaround when continuing the <rich:validator> approach.
You've basically following options:
Maunally write an oncomplete script which finds the validation error messages and then finds the associated inputs and then set the desired marker style class on it.
Report an issue to RichFaces guys and ask them to add a marker style class to invalid inputs via <rich:validator>, so you could style them individually.
Drop <rich:validator> and replace it by server side validation via <f:ajax>.
I wrote a web program in the Netbeans IDE 7.1.2 in java server faces
and I have a problem with ui:repeat tag
<h:form id="arrangmentForm" rendered="false" >
<ui:repeat value="#{arrangement.arItemArrangment}" var="itemArrangment" >
<h:panelGrid style="position: absolute;top:#{itemArrangment.place.top / 10}px;left: #{itemArrangment.place.left/10}px;height: 30px;width:30px">
<h:commandLink id="linkItemArrangment" actionListener="#{arrangement.showbtnArrangement()}" style="text-decoration: none;color: black">
<p:graphicImage value="../images/#{itemArrangment.place.objType}.jpg" />
<h:outputText value="#{itemArrangment.place.objTitle}" />
<br />
<h:outputText value="#{itemArrangment.gethOrder().gethOrdersTotal()}" />
<br />
<f:setPropertyActionListener value="#{itemArrangment}" target="#{arrangement.selectPlace}" />
</h:commandLink>
</h:panelGrid>
</ui:repeat>
</h:form>
This code works fine in Netbeans.
When I tried to deploy my program to a web server (Tomcat7, Glassfish open source and enterprise edition) the ui tag didn't work, though, and in my web browser I just receive the form tag and nothing else.
You have rendered="false" in your h:form so nothing is display. It's the normal behavior.
If you want to display the content of the form remove the rendered="false"
I came to strange behaviour of my application. Command buttons start to invoke actions on second hit. On first - nothing happens. It takes effect on firefox and chromium, but in epiphany works as usual.
My environment:
- ubuntu 11.04
- glassfish 3.1.1
- jsf 2.X
- primefaces 3.2
- firefox 12.0
- epiphany 2.30.6
Code example:
<ui:define name="content">
<h:form id="form">
<h:panelGrid id="panelGrid" columns="3">
<h:outputText value="#{msg.fieUserName}:"/>
<h:inputText id="name" value="#{userBb.editedUser.username}" />
<h:message for="name" styleClass="error_msg"/>
<h:outputText value="#{msg.fieUserDescription}:"/>
<h:inputText id="description" value="#{userBb.editedUser.description}" />
<h:message for="description" styleClass="error_msg"/>
<h:outputText value="#{msg.fieUserPassword}:"/>
<h:inputSecret id="password" value="#{userBb.editedUser.password}" redisplay="true"/>
<h:message for="password" styleClass="error_msg"/>
<h:outputText value="#{msg.fieUserRights}:"/>
<p:selectOneMenu id= "rights"
value= "#{userBb.editedUserGroup}"
converter="#{pGroupOfUsersConverter}">
<f:selectItems
value ="#{groupDao.findAll()}"
var ="row"
itemLabel="#{groupDao.rightsDescription(row.id)}"
itemValue="#{row.groupname}"
>
</f:selectItems>
</p:selectOneMenu>
<h:message for="rights" styleClass="error_msg"/>
<h:outputText value="#{msg.fiePorofolioName}:" rendered="#{userBb.chosenNew}"/>
<h:inputText id="portName" value="#{userBb.portfelForNewUser.nazwa}" rendered="#{userBb.chosenNew}">
<f:validateBean disabled="true" />
</h:inputText>
<h:message for="portName" styleClass="error_msg" rendered="#{userBb.chosenNew}"/>
<h:outputText value="#{msg.fiePotofolioCurrency}:" rendered="#{userBb.chosenNew}"/>
<p:selectOneMenu id= "waldep"
value= "#{userBb.portfelForNewUser.walutaDepozytowa}"
converter="#{igConverter}"
rendered= "#{userBb.chosenNew}"
>
<f:selectItems value= "#{igDao.waluty}"
var= "row"
itemLabel="#{row.nazwa}"/>
</p:selectOneMenu>
<h:message for="waldep" styleClass="error_msg" rendered="#{userBb.chosenNew}"/>
</h:panelGrid>
<h:panelGrid columns="2">
<h:commandButton value="#{msg.butCreate}" action="#{userBb.formCreate()}" rendered="#{userBb.chosenNew}" />
<h:commandButton value="#{msg.butSave}" action="#{userBb.formEdit()}" rendered="#{!userBb.chosenNew}"/>
<h:commandButton value="#{msg.butBack}" action="#{userBb.formBack()}"/>
</h:panelGrid>
</h:form>
</ui:define>
In this example method userBb.formCreate() is invoked only on second click on command button although button is visible. When fields are not properly filled up than appropriate messages appear next to them, but... only on second click! Any advice?
I check out points from: this advice, but not found solution.
Ok, I found what was wrong. So:
Appearance of the problem:
I've got a page for user data. Some input items and command buttons. When clicking "Create" button, input data is checked out. If data is ok user is created and table of users appears, or when there are errors - errors messages appear and user stays on the same page:
I found some erratic behavior. Nothing has happened on first click (action), only second and subsequent actions have an effect. But. This behavior was related to kind of web browser I use.
All actions takes place from the first click, in webrowsers: epiphany and konqueror. Although in firefox and chromium I observed this erratic behavior which I described above. Code for a command button was:
<h:commandButton value="#{msg.butCreate}" action="#{userBb.formCreate()}" rendered="#{userBb.chosenNew}"/>
Different behaviors in different webbrowsers.
The cause.
The cause was enumerated by #Balusc in his note, which I read roughly first time. It was indeed pt. 7.
The solution.
I've tried to change button declaration this way:
<h:commandButton value="#{msg.butCreate}" action="#{userBb.formCreate()}" rendered="#{userBb.chosenNew}">
<f:ajax render="userForm"/>
</h:commandButton>
where userForm was proper id of h:form. No result, still only second and subsequent clicks has an effect - shows error messages.
So I changed declaration command button from previous page, that invoked erratic behavior page. Originally it was:
<p:commandButton value="#{msg.butNew}" action="#{userBb.actionNew()}"/>
primefaces command button. And that was it, as Balusc wrote: "If a parent of the with the UICommand button is been rendered/updated by an ajax request beforehand, then the first action will always fail."
So I changed declaration to:
<p:commandButton value="#{msg.butNew}" action="#{userBb.actionNew()}" ajax="false"/>
And that's it. It works fine in any browser, for the first action.
I have developed a simple login form to be used in my JSF + PrimeFaces page:
<form action="j_security_check" method="post">
<p:dialog modal="true" header="Login" widgetVar="loginDlg">
<h:panelGrid columns="3" cellpadding="5">
<h:outputLabel for="j_username">Username:</h:outputLabel>
<h:inputText id="j_username" required="true" />
<h:message for="j_username" />
<h:outputLabel for="j_password">Password:</h:outputLabel>
<h:inputSecret id="j_password" required="true" />
<h:message for="j_password" />
<br />
<h:commandButton value="Login" />
</h:panelGrid>
</p:dialog>
</form>
Tried with an empty password, but the missing password (that is required) is not caught by h:message component. I have also switched to a p:commandButton thinking that the problem could have been in the Ajax behaviour of the button, but the page is not rendered because PrimeFaces complains about the CommandButton not being inside a form element. The exception thrown by the container is:
com.sun.enterprise.security.auth.login.common.LoginException: Login failed: Access denied on empty password for user pippo
To summarize, I have 2 questions:
Why the missing password doesn't produce a message before the form is submitted?
How can I catch a LoginException and display the error message inside the dialog?
The j_security_check request is handled by the web container, not by JSF. That explains that the required="true" won't work. It works only when you use JSF <h:form> and programmatic login by HttpServletRequest#login() in the action method associated with the command button.
Best what you can do is to confiure a <form-error-page> in web.xml pointing to the very same URL as the <form-login-page>. You could then check if the request has been forwarded by j_security_check itself, which would mean that a login error has occurred.
<h:panelGroup rendered="#{requestScope['javax.servlet.forward.servlet_path'] == '/j_security_check'}">
<h:outputText value="Unknown login, please try again" styleClass="error" />
</h:panelGroup>
Use this instead of the <h:message>.
As to why <p:commandButton> complains that there's no form is simply because you didn't use <h:form>.
Unrelated to the concrete problem, that <form> (or <h:form> whenever you would decide to switch to programmatic login) can better be placed in the body of <p:dialog>, not outside. The <p:dialog> can by JS be relocated to end of body which would cause it not to be in a form anymore.