Custom validator not invoked when fields are empty - validation

I have implemented a custom validator for my screen referring to the example given here.
But in my case, my validator method is not invoked if I don't enter any values in any of the field. So the check for empty fields is never done. The required messages are displayed everytime.
If I removed the required attributes, even in that case the validator is invoked only if the fields have some value in them. How do I get all my validations to be done in the validator class?
My xhtml:
<h:form>
<p:messages id="message" closable="true"/>
<h:panelGrid columns="3" id="changePassPanel">
<h:outputLabel for="pwd0" value="Current password :" />
<p:password id="pwd0" value="#{homeBean.password1}">
<f:validator validatorId="PasswordValidator"></f:validator>
<f:attribute name="pwd1" value="#{pwd1}" />
<f:attribute name="pwd2" value="#{pwd2}" />
</p:password>
<h:outputLabel for="pwd1" value="New password :" />
<p:password id="pwd1" value="#{homeBean.password2}" binding="#{pwd1}"/>
<h:outputLabel for="pwd2" value="Confirm new password :" />
<p:password id="pwd2" binding="#{pwd2}"/>
</h:panelGrid>
<p:commandButton id="saveButton" value="Save" validateClient="true"/>
</h:form>

Related

Validation messages across required fields with converter

I have a form with multiple fields, of which I need one of them required to continue or a group of them. For simplicity, I'll just paste a simpler version of my code here
<h:form id="searchForm">
<p:growl for="searchForm" showDetail="true" showSummary="true"/>
<p:inputText id="name"
value="#{backingBean.name}"
required="#{backingBean.nameRequired and backingBean.masterRequired}">
<p:ajax />
</p:inputText>
<h:panelGroup id="dateForm">
<p:inputMask id="date"
value="#{backingBean.date}"
mask="99/99/9999"
required="#{backingBean.dateRequired and backingBean.masterRequired}"
converterMessage="Please insert using format dd/mm/yyyy">
<f:convertDateTime pattern="dd/MM/yyyy" />
<f:validator validatorId="dateValidator" />
<p:ajax update="dateForm" />
</p:inputMask>
</h:panelGroup>
<p:selectOneMenu id="documentType" effect="fade"
value="#{backingBean.documentType}"
required="#{backingBean.documentRequired and backingBean.masterRequired}">
<f:selectItem itemLabel="Select document type" noSelectOption="true" />
<f:selectItems
value="#{constantsController.docType.entrySet()}"
var="entry" itemValue="#{entry.key}" itemLabel="#{entry.value}" />
<p:ajax />
</p:selectOneMenu>
<p:inputText id="documentNumber"
value="#{backingBean.documentNumber}"
required="#{backingBean.documentRequired and backingBean.masterRequired}">
<p:ajax />
</p:inputText>
<p:commandButton id="searchButton"
value="Search"
action="#{controllerBean.submitSearch}"
icon="ui-icon-search">
<p:ajax
listener="#{backingBean.checkRequired()}" update="#form" />
</p:commandButton>
</h:form>
When all fields are empty, the is shown as it should. Now what I need is the inputMask date to only show the converter message and the validation message. I need it to not show the message when the requiredMessage will try to be shown.
I tried putting a <p:message for="date" rendered="#{!empty param['date']}" /> but it does not work, since it is not rendered on the first load, and ajax does not update the panelGroup, I think it is because since I gave an invalid value to the converter, it does not fire the update.
Additional information:
As you can see, I have multiple required fields, I need at least one of these:
-name
-date
-document type + document number
Now, to validate the required fields, I'm doing the following on my backing bean:
public void checkRequired() {
nameRequired = name.equals("");
dateRequired = date == null;
documentRequired = documentType.equals("") || documentNumber.equals("");
masterRequired = nameRequired && dateRequired && documentRequired;
if(masterRequired)
{
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_WARN, "Incomplete form",
"Please insert at least 1 field");
FacesContext.getCurrentInstance().addMessage("searchForm", message);
return;
}
}

Primefaces 2 <h:form> and 2<p:message> confusion

My login page has 2 forms, 1 for login itself, and another one to create new users and they are in a tab view(p:tabView), so users will never see both on the page, it would be, one or another.
The problem is that everytime that a valitation fails on login tab, the failure is also shown in the new user tab, and vice-versa.
How to handle this? i tried to set update property in the buttoncommand, but it did not work
see my code below:
<p:tabView id="loginTabView" orientation="right" style="margin-bottom:20px" styleClass="login_fields_panel">
<p:tab title="Acesso" id="acessoTab" >
<h:form>
<h3><h:outputText value="#{bundle.loginHello}" escape="false"/></h3>
<p:messages id="messages_login" showDetail="false" autoUpdate="true" closable="true" showIcon="true"/>
<p:outputLabel for="email" value="#{bundle.label_email}"/>
<p:inputText value="#{loginMB.email}" label="#{bundle.label_email}" id="email" required="true" validatorMessage="#{bundle.emailInvalido}" size="45">
<f:validateRegex pattern="^[\w-\.]+#([\w-]+\.)+[\w-]{2,4}$" for="email" />
</p:inputText>
<br/>
<p:outputLabel for="senha" value="#{bundle.label_password}" />
<p:password value="#{loginMB.password}" id="senha" label="#{bundle.label_password}" required="true" size="45"/>
<br/><br/>
<p:commandButton action="#{loginMB.login}" value="#{bundle.btn_login}" ajax="false" update="messages_login"/>
</h:form>
</p:tab>
<p:tab title="Faça seu cadastro aqui" id="newUserPanel" >
<h:form id="formNewUser">
<h3><h:outputText value="#{bundle.loginHello}" escape="false"/></h3>
<p:messages id="messages_new" showDetail="false" autoUpdate="true" closable="true" showIcon="true" />
<h:panelGrid columns="2" id="matchGrid" cellpadding="1">
<p:outputLabel for="email" value="#{bundle.label_name}: "/>
<p:inputText value="#{loginMB.email}" label="#{bundle.label_name}:" id="name" required="true" validatorMessage="#{bundle.emailInvalido}" size="45" maxlength="100">
</p:inputText>
<p:outputLabel for="email" value="#{bundle.label_email}: "/>
<p:inputText value="#{loginMB.email}" label="#{bundle.label_email}" id="email" required="true" validatorMessage="#{bundle.emailInvalido}" size="45">
<f:validateRegex pattern="^[\w-\.]+#([\w-]+\.)+[\w-]{2,4}$" for="email" />
</p:inputText>
<p:outputLabel for="senha" value="#{bundle.label_password}" />
<p:password value="#{loginMB.password}" id="senha" label="#{bundle.label_password}" required="true" size="45"/>
<p:outputLabel for="senhaConfirmacao" value="#{bundle.label_password_confirmacao}" />
<p:password value="#{loginMB.password}" id="senhaConfirmacao" label="#{bundle.label_password_confirmacao}" required="true" size="45"/>
<p:outputLabel for="birthday" value="#{bundle.label_birthday}" />
<p:calendar id="birthday" value="#{calendarView.date2}" required="true" size="45" pattern="dd/MM/yyyy"/>
</h:panelGrid>
<br/><br/>
<p:commandButton id="btn_create" action="#{loginMB.createUser}" value="#{bundle.btn_criar_usuario}" ajax="true" update="messages_new"/>
</h:form>
</p:tab>
thanks
The described problem with two forms and two message components is actually two-fold:
You're using autoUpdate="true" on those message components. So regardless of what you specify in update attribute, those message components will be auto-updated.
You need to either remove the autoUpdate="true" from the message components, or add ignoreAutoUpdate="true" to the command component.
You're using ajax="false" on the first button. This forces a full page reload. Do note that all ajax-related attribtes such as process and update are ignored in such case.
You need to either re-enable ajax on the first button, or to add redisplay="false" to the second message component.

Submit a form without validitating required fields primefaces

I want to have a form with JSF (Primefaces) to have a required field (the username is this example) to be required when saved. Also you can add books to every user, a user can have 0 ... n books. If you add a new book, it is required to give it an author and a name.
I tried it with the code below and already tried many ways of the Partial Processing of Primefaces. However, it is not working correctly. Sometimes I have to enter the required username to add a book or save it not working at all. Is there a way, to only check the required username on save and ignore the required author and bookname?
This is the code for the example:
<h:form>
<p:outputPanel id=„userdetails“>
<p:inputText id="name" value="#{bean.name}" />
</p:outputPanel>
<p:inputText id="txt_title" value="#{createBookBean.book.title}"
required="true" />
<p:inputText id="txt_author" required="true"
value="#{createBookBean.book.author}" />
<p:commandButton value="Reset" type="reset" />
<p:commandButton id="btn_add" value="Add"
update="books msgs #parent" action="#{createBookBean.reinit}">
<p:collector value="#{createBookBean.book}"
addTo="#{createBookBean.books}" />
</p:commandButton>
<p:outputPanel id="books">
<p:dataTable id="booksTable" value="#{createBookBean.books}"
var="book">
<h:outputText value="#{book.title}" />
<h:outputText value="#{book.author}" />
<p:column>
<p:commandLink value="Remove" update=":form:books"
process=":form:books">
<p:collector value="#{book}"
removeFrom="#{createBookBean.books}" />
</p:commandLink>
</p:column>
</p:dataTable>
</p:outputPanel>
<p:commandButton value="Save" update="msgs" process="#form"
action="#{bean.save()}"></p:commandButton> // button to save, and ignore required bookname
</h:form>
// button to save, and ignore required bookname
For that purpose you can use immediate attribute of commandButton:
<p:commandButton value="Save" update="msgs" process="#form"
action="#{bean.save()}" immediate="true" />

JSF Validate on keyup event

i want to implement a validation for a username. The 'normal' way to do it
is something like that:
<h:outputText for="username" value="Username:" />
<p:inputText id="username" value="#{registerService.username}" >
<f:validator binding="#{usernameValidator}" />
</p:inputText>
<p:message for="username" />
<p:commandButton type="submit" value="Submit" action="#{registerService.addUser}" ajax="false" update="panel" validateClient="true" />
But what i now want to do is to validate the username everytime
the user presses a key in the username inputText without pressing
the commandButton.
So each character should trigger the validation and should update
the messages field for username to show the user instantly if the
username is already present in database or not.
How can i do that?
Found:
Ajax Listener
This triggers the validation!
<h:inputText id="foo" value="#{bean.foo}">
<f:ajax event="keyup" execute="#this" render="fooMessage" />
<f:validator validatorId="fooValidator" />
</h:inputText>
<h:message id="fooMessage" for="foo" />

Trigger OmniFaces multi field validation after focus lost

I need to create a validation on Calendar components - Begin/End. OmniFaces supports multi field validation very well, like here:
<h:panelGrid columns="3">
<h:outputLabel for="startDate" value="Start date" />
<h:inputText id="startDate" value"#{booking.reservation.startDate}" required="true"
requiredMessage="Please enter start date"
converterMessage="Please enter format yyyy-MM-dd">
<f:convertDateTime pattern="yyyy-MM-dd" />
</h:inputText>
<h:message for="startDate" />
<h:outputLabel for="endDate" value="End date" />
<h:inputText id="endDate" value"#{booking.reservation.endDate}" required="true"
requiredMessage="Please enter end date"
converterMessage="Please enter format yyyy-MM-dd">
<f:convertDateTime pattern="yyyy-MM-dd" />
</h:inputText>
<h:panelGroup>
<h:message for="endDate" />
<h:message for="order" />
<o:validateOrder id="order" components="startDate endDate"
message="End date must be after start date" />
</h:panelGroup>
</h:panelGrid>
<h:commandButton value="submit" action="#{booking.submit}">
<f:ajax execute="#form" render="#form" />
</h:commandButton>
But, In this example validation is triggered after manually submit. And I need to validate after focus (of Calendar) is lost. How can I achieve that? Thanks.
The multi field validators from OmniFaces can be referenced in <f:ajax execute>. The "focus lost" event is the blur event. Thus, this should do:
<h:inputText ...>
<f:ajax event="blur" execute="startDate endDate order" render="m_startDate m_endDate m_order" />
</h:inputText>
where m_startDate, etc are the IDs of the <h:message> components like so
<h:message id="m_startDate" for="startDate" />

Resources