Icons with a FacesMessage when validating - validation

PrimeFaces/JSF 2.0
When you use p:message.... and say your outputText has required="true", you see the error icon in the message displayed to the right of the field if the user leaves the field blank.
<!-- NAME -->
<p:panelGrid styleClass="noBorders" columns="2" columnClasses="inputText" style="width:600px">
<h:inputText id="Name" size="60" maxlength="70" required="true" styleClass="#{not component.valid ? 'ui-input-invalid' : ''}" style="width: 300px" value="#{tinRequestBean.name}" >
<f:validator validatorId="gov.irs.eservices.tm.validations.NameValidator" />
</h:inputText>
<p:message for="Name" display="default" style="color: red" />
</p:panelGrid>
However, if you use a Validator to check the contents of the field in some way, the standard FacesMessage, even with FacesMessage.SEVERITY_ERROR, the error icon does not show up.
if (msgStr.length() > 0) {
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "TIN: Validation error: " msgStr, null);
throw new ValidatorException(msg);
}
Does anyone know a way to create a FacesMessage with an icon attached? It's certainly not in the constructor.

Set the display="both" on the <p:message/>(or just leave that attribute out altogether, both is the default). This will display both the text and the icon. As far as I can tell, default is not a valid option

Related

Showing JSF validation errors for several fields with more than h:message

A form with validations on several input fields should show stylish error messages with an icon in front of the message contained in a red box.
The h:panelGroup containing icon and message must be rendered only in case of an error.
With just one validated input field this would work:
<h:panelGroup rendered="#{facesContext.validationFailed}"
But with more than one input field all error panel groups are visible, even those without error showing no text but the icon in a red box.
My solution is now to have a validator for each input and add an attribute ´´validationFailed´´ to each validator.
<p:inputNumber id="mileage" validator="#{mileageValidator.validate}"></p:inputNumber>
<h:panelGroup rendered="#{mileageValidator.validationFailed}" styleClass="wizard-alert-box">
<div class="wizard-alert-content-margin">
<h:graphicImage name="attention.png"/>
<h:message id="invalid-mileage" for="mileage" showSummary="true" showDetail="false"/>
</div>
</h:panelGroup>
<p:calendar id="date" validator="#{dateValidator.validate}"></p:calendar>
<h:panelGroup rendered="#{dateValidator.validationFailed}" styleClass="wizard-alert-box">
<div class="wizard-alert-content-margin">
<h:graphicImage name="attention.png"/>
<h:message id="invalid-date" for="date" showSummary="true" showDetail="false"/>
</div>
</h:panelGroup>
And here is one of the validators:
#Named("mileageValidator")
public class MileageValidator {
#Getter
private boolean validationFailed;
public void validate(FacesContext context, UIComponent component, Object value) {
validationFailed = value == null;
if (validationFailed) {
throw new ValidatorException(new FacesMessage("mileage empty"));
}
}
}

JSF ajax render message and redirect

I have a JSF application where users login in a login form inserting their email and password. The ManagedBean has the following 2 methods.
The method checkIdentity1() returns an URL ("" if the validation is incorrect in order to stay in the same page, or /useraccount.xhtml if inserted data is ok in order to go to next page).
The method checkIdentity2() returns a boolean value (false if the validation is wrong in order to show a message, true if it is ok).
loginManagedBean.java
public String checkIdentity1()
{
String strResponse="";
//check id
if(email.equals("jose#a.com") && password.equals("1234"))
{
strResponse="/useraccount.xhtml?faces-redirect=true";
} else {
}
//
return strResponse;
}
public boolean checkIdentity2()
{
boolean bResponse=false;
//check id
if(email.equals("jose#a.com") && password.equals("1234"))
{
//setpassIncorrecta(false);
} else {
bResponse=true;
}
//
return bResponse;
}
What I am trying to do is to mix ajax and JSF to show "Email and/or password incorrect" when I click Login button and validation fails and go to account.xhtml when validation is ok. But when I insert incorrect email and password no message is displayed, and when I insert them correctly the page is no redirected to account.xhtml. What am I doing wrong?
This is my Facelet
<h:form>
<!--Email-->
<h:inputText id="email" label="email" required="true" size="32" maxlength="32"
value="#{loginManagedBean.email}"
requiredMessage="Insert your email">
</h:inputText>
<h:message for="email" />
<!--Password-->
<h:inputSecret id="password" label="password" required="true" size="32" maxlength="40"
value="#{loginManagedBean.password}"
requiredMessage="Insert your password">
</h:inputSecret>
<h:message for="password" />
<!--Button-->
<h:commandButton value="Login" action="#{loginManagedBean.checkIdentity1()}">
<f:ajax execute="#form" render=":loginErrorMessage" />
</h:commandButton>
</h:form>
<h:panelGroup id="loginErrorMessage">
<h:outputText value="Email and/or password incorrect" rendered="#{!loginManagedBean.checkIdentity2()}" />
</h:panelGroup>
Like I explained in the comment, that's just the way JSF works: if a request fails validation, the action method will not be executed. That's defined the JSF request processing lifecycle (which I won't get into here). For the purpose of this answer, all you need to know is that the validation of request parameters happens before the action methods are considered. That being said, if the validation fails, the request processing is short-circuited there and then. To achieve what you're looking for, you should consider the following:
To conditionally render that component, you can examine the validation status in your page:
<h:outputText value="Email and/or password incorrect" rendered="#{facesContext.validationFailed}" />
Ideally, you should just use the <h:messages/> component, where you don't need to manage message display yourself
JSF will stay on the same page by default, if the validation fails, so you needn't take any special steps to that effect

How to validate p:pickList to require at least one selection

I have used column picklist to customize columns of table on page and I want to show dialog message (Atleast one column should be enabled) if user disables all the columns from picklist. That means user should keep atleast one column in enable box.
<p:dialog id="pickListDialog" header="Customize View"
widgetVar="dlg">
<h:panelGrid>
<p:pickList id="columnPickList"
value="#{Class_Name.columns}" var="col"
itemLabel="#{Class_Name.columnPickList.columnsDisplayMap.get(col)}"
itemValue="#{col}">
<f:facet name="sourceCaption">Disabled</f:facet>
<f:facet name="targetCaption">Enabled</f:facet>
</p:pickList>
<p:commandButton value="Submit"
actionListener="#{Class_Name.columnPickList.saveColumns}" onclick="return disableClick();"
ajax="false" />
</h:panelGrid>
</p:dialog>
Javascript method -
function disableClick(){
if (document.getElementById("form:columnPickList_target").value == ""){
alert("Please Select Atleast One Field");
return false;
}
}
Here I have used Javascript for this. But I want to do this by JSF .
can anyone please tell me ?
Case 1 : Using required attribute
<p:pickList id="columnPickList" required="true" requiredMessage="Atleast one column should be enabled"
value="#{Class_Name.columns}" var="col"
itemLabel="#{Class_Name.columnPickList.columnsDisplayMap.get(col)}"
itemValue="#{col}">
<f:facet name="sourceCaption">Disabled</f:facet>
<f:facet name="targetCaption">Enabled</f:facet>
</p:pickList>
Case 2 : Opening dialog from backing bean
public void saveColumns()
{
validateColumns();
//doSomthing
}
public void validateColumns() {
//check if picklist target is empty
if(columns.getTarget().size()==0)
{
//open dialog
message="Atleast one column should be enabled";
RequestContext.getCurrentInstance().execute("validationDialog.show()");
}
}
private String message; //getter and setter
dialog :
<p:dialog id="valid" widgetVar="validationDialog">
<p:outputLabel value="#{yourbean.message}" />
</dialog>

JSF selectOneMenu validation and ajax rendering

I have a validation on my selectOneMenu to prevent the user to select "None" item in the list.
<h:selectOneMenu id="selectMenu" value="#{bean.selectedValue}" required="true" requiredMessage="Please select an item">
<f:ajax render="toRender selectMenuMessage" listener="#{bean.onSelect}"/>
<f:selectItem itemLabel="None" noSelectionOption="true"/>
<f:selectItems value="#{bean.items}" var="item" itemValue="#{item.id}" itemLabel="#{item.label}"/>
</h:selectOneMenu>
I have my panel below and a want to show it only when my item is not "None".
So when I select "None", the message should render and the panel disappear.
<h:panelGroup id="toRender">
<h:panelGrid rendered="#{bean.selectedValue == 0 ? false : true">
...
</h:panelGrid>
</h:panelGroup>
It's working without the validation but I can't make both work.. It's like if validation prevents rendering.
Any suggestion?
Thanks
I guess that bean.selectedValue is an Integer, so try this:
<f:selectItem itemValue="0" itemLabel="None" noSelectionOption="true"/>
Edit:
Ah sorry, I think misunderstood your problem a little bit.
The problem here is, that if you are requiering a value for the selectOneMenu the value will not submitted if it is empty. And if the item with noSelectionOption="true" is selected, it will be handled as empty, so no value will be submitted. When you are checking against bean.selectedValue == 0, selectedValue will never - except maybe initially - be 0, because when you select the item with value 0 it will not be submitted, as described above.
So you are right, your validation and the check for bean.selectedValue == 0 can not work together. I would recommend you to just remove the validation.
If this is no option for you, please explain me why you need it to work that way in more details.
I have a response, it's not the solution but it's another way to do this...
<h:selectOneMenu id="selectMenu" value="#{bean.selectedValue}">
<f:ajax render="toRender selectMenuMessage" listener="#{bean.onSelect}"/>
<f:selectItem itemLabel="None" noSelectionOption="true"/>
<f:selectItems value="#{bean.items}" var="item" itemValue="#{item.id}" itemLabel="#{item.label}"/>
</h:selectOneMenu>
And in the bean
public void onSelect() {
if(this.selectedValue != 0) {
// Do smthg here
} else {
// Display error message
UIComponent component = Outils.getFacesContext().getViewRoot().findComponent(":form:selectMenu");
if(component != null) {
Outils.getFacesContext().addMessage(component.getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, "", "Test msg"));
}
}
}
This way the validation process is not launched and the verification is done in the bean.
If someone find something better, let me know!

How to skip action when validation with a custom validator fails?

I have a small webapplication for a library, with a customized ISBN validator. My .xhtml page for adding a book looks like this:
<fieldset>
<h:messages/>
<ul>
<li>
<h:outputLabel for="isbn" value="#{labels.isbn}:" />
<h:inputText id="isbn" value="#{addController.book.isbn.isbnValue}" required="true" requiredMessage="- ISBN must be filled in.">
<f:validator validatorId="isbnValidator" />
</h:inputText>
</li>
<li>
<h:outputLabel for="title" value="#{labels.title}:" />
<h:inputText id="title" value="#{addController.book.title}" required="true" requiredMessage="- Title must be filled in."/>
</li>
<li>
<h:outputLabel for="name" value="#{labels.name}:" />
<h:inputText id="name" value="#{addController.book.person.name}" required="true" requiredMessage="- Name must be filled in."/>
</li>
<li>
<h:outputLabel for="firstname" value="#{labels.firstname}:" />
<h:inputText id="firstname" value="#{addController.book.person.firstname}" />
</li>
</ul>
<h:commandButton id="addButton" action="#{addController.save}" value="#{labels.add}" />
<h:commandButton id="cancelButton" action="bookOverview" value="#{labels.cancel}" />
</fieldset>
</ui:define>
The isbnValidator of the first input field is this class:
private Isbn isbn;
#Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
isbn = new Isbn((String) value);
if (!isbn.isIsbn17Characters()) {
addMessageToContext(context, "- ISBN needs to have 17 characters");
}
if (isbn.isIsbn17Characters() && !isbn.isIsbnInRightFormat()) {
addMessageToContext(context, "- Wrong format, it should be like 'XXX-XX-XXX-XXXX-X'");
}
if (isbn.isIsbn17Characters() && isbn.isIsbnInRightFormat() && !isbn.isIsbnFormatValid()) {
addMessageToContext(context, "- ISBN can only contain numbers, and no other tokens");
}
if (isbn.isIsbn17Characters() && isbn.isIsbnInRightFormat() && isbn.isIsbnFormatValid()
&& !isbn.isLastNumberValid()) {
addMessageToContext(context, "- Last number of the ISBN should be " + isbn.getCorrectLastNumber()
+ " with those 12 numbers");
}
}
public static void addMessageToContext(FacesContext context, String message) {
FacesMessage facesMessage = new FacesMessage();
facesMessage.setSummary(message);
facesMessage.setDetail(message);
context.addMessage("isbn", facesMessage);
}
When I click the 'add' button, the book should be added to the database.
When the ISBNfield, namefield or titlefield aren't filled in, I get the corresponding error message. But when my fields are filled in, and the ISBN validation fails, he shows the error message, but he still adds the book (with a wrong ISBN-number) to the database.
A solution which I thought about: If my messages tags is not empty, he shouldn't add the book to the database. But how can I check that?
Or is there a better solution to my problem?
The validation error message handling is wrong. You need to throw a ValidatorException with a FacesMessage instead of adding the FacesMessage manually.
So instead of all those
addMessageToContext(context, "- ISBN needs to have 17 characters");
you need to do
throw new ValidatorException(new FacesMessage("- ISBN needs to have 17 characters"));
This is for JSF sign that the input is invalid and hence the action method won't be invoked. You also don't need to specify the client ID, it will just end up in the <h:message> associated with the input component where this validator is fired on.

Resources