I use the same bean field, a string called email, for different purposes (register, recovery password, login). So, I wish navigate between views/flows and bean fields must clean automatically, but this behavior don't happen.
It's a JSF2/Spring project
Flow definition
<var name="viewScope.loginFields" class="es.project.viewBean.ConnectionFields" />
<view-state id="login" view="login.xhtml" model="loginFields">
<transition on="entry" to="connect"/>
<transition on="recoveryPass" to="recovery" />
</view-state>
<view-state id="recovery" view="recovery.xhtml" model="loginFields">
<transition on="return" to="login" />
<transition on="sendPass" to="recoveryPass" />
</view-state>
Bean definition
#Service("loginFields")
public class ConnectionFields implements Serializable {
private static final long serialVersionUID = 1L;
private static Logger logger=LogManager.getLogger(ConnectionFields.class);
#NotNull(message="{field.notEmpty.validation}")
#Email(message="{field.email.validation}")
private String email;
#NotNull(message="{field.notEmpty.validation}")
#Size(min=6,max=12,message="{field.size.validation}")
#Pattern(regexp="^[a-zA-Z0-9]*$",message="{field.onlyAlpha.validation}")
private String password;
#NotNull(message="{field.notEmpty.validation}")
#Size(min=6,max=12,message="{field.size.validation}")
#Pattern(regexp="^[a-zA-Z0-9]*$",message="{field.onlyAlpha.validation}")
private String passwordRepeated;
#NotNull(message="{field.notEmpty.validation}")
#Email(message="{field.email.validation}")
private String emailRepeated;
...........
...........
...........
}
recovery.xhtml
<h:form id="formRecovery">
<h:panelGroup layout="block" id="containerFormRecovery" styleClass="containerFormRecovery">
<p:focus />
<h:panelGroup layout="block" styleClass="formRecovery-row">
<h:outputLabel for="email" value="#{msg['email.txt']}" />
<h:inputText id="email" value="#{loginFields.email}" title="#{msg['email.txt.title']}" alt="#{msg['email.txt.alt']}" styleClass="#{component.valid ? '' : 'invalid'}" size="35" tabindex="1">
<f:validateBean for="email" />
<p:ajax event="blur" update="#this emailError"/>
</h:inputText>
<h:message for="email" id="emailError" styleClass="messageError" />
</h:panelGroup>
<h:panelGroup layout="block" styleClass="formRecovery-row">
<p:captcha id="captcha" theme="white" requiredMessage="#{msg['captcha.required']}" tabindex="2">
</p:captcha>
<h:message for="captcha" id="captchaError" styleClass="messageError"/>
</h:panelGroup>
<h:panelGroup layout="block" id="containerRecoveryButtons" styleClass="containerRecoveryButtons">
<h:commandButton value="#{msg['send.btn']}" title="#{msg['send.btn.title']}" alt="#{msg['send.btn.title']}" action="sendPass" tabindex="3" />
</h:panelGroup>
</h:panelGroup>
</h:form>
<h:panelGroup>
<h:commandLink value="#{msg['return.btn']}" title="#{msg['return.btn.title']}" alt="#{msg['return.btn.alt']}" action="return" tabindex="4" />
</h:panelGroup>
login.xthml
<h:form id="formLogin">
<h:panelGroup layout="block" id="containerFormLogin" styleClass="containerFormLogin">
<p:focus />
<h:panelGroup layout="block" styleClass="formLogin-row">
<h:outputLabel for="email" value="#{msg['email.txt']}" />
<h:inputText id="email" value="#{loginFields.email}" title="#{msg['email.txt.title']}" alt="#{msg['email.txt.alt']}" styleClass="#{component.valid ? '' : 'invalid'}" size="35" tabindex="2">
<f:validateBean for="email" />
<p:ajax event="blur" update="#this emailError" />
</h:inputText>
<h:message for="email" id="emailError" styleClass="messageError" />
</h:panelGroup>
<h:panelGroup layout="block" styleClass="formLogin-row">
<h:outputLabel for="password" value="#{msg['pass.txt']}" />
<p:password id="password" value="#{loginFields.password}" title="#{msg['pass.txt.title']}" alt="#{msg['pass.txt.alt']}"
styleClass="#{component.valid ? '' : 'invalid'}" size="35" tabindex="3">
<f:validateBean for="password" />
<p:ajax event="blur" update="#this passwordError" />
</p:password>
<h:message for="password" id="passwordError" styleClass="messageError" />
</h:panelGroup>
<p>
<h:outputLabel for="remember" value="#{msg['rememberSession.msg.check']}" />
<h:selectBooleanCheckbox id="remember" value="#{loginFields.remember}" tabindex="4" title="#{msg['rememberSession.title.check']}" />
</p>
<h:panelGroup layout="block" id="containerLoginButtons" styleClass="containerLoginButtons">
<h:commandButton value="#{msg['login.long.btn']}" action="entry" tabindex="5" title="#{msg['login.long.btn.title']}" alt="#{msg['login.long.btn.alt']}" />
</h:panelGroup>
</h:panelGroup>
</h:form>
<p>
<h:form>
<h:commandLink value="#{msg['recoveryPassword.msg.link']}" action="recoveryPass" />
</h:form>
</p>
On above example, my idea is to navigate to RecoveryPassword page from Login page and viceversa, and I would like email field reset value itself when I change view, but email never reset the value.
One approach would be to clear the value in the <transition> or the <on-entry> of your states. Either with just a setter method or with a custom method (e.g. reset()). We do this for various other conditions where entering a state requires clearing a field.
e.g.
<view-state id="recovery">
<on-entry>
<set name="loginFields.email" value="''"/>
</on-entry>
...
</view-state>
Related
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.
I have a jsf Form with fields, submit and messages for it
<h:form id="loginForm">
<h:outputText value="Введите логин и пароль:"/>
<h:panelGrid columns="2">
<h:outputLabel for="email" value="E-Mail:"/>
<h:inputText id="email" value="#{sign.email}" required="true" requiredMessage="Введите e-mail" validatorMessage="email должен быть вида abc#abc.abc">
<f:validateRegex pattern="[\w\.-]*[a-zA-Z0-9_]#[\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]" />
</h:inputText>
<h:outputLabel for="password" value="Password:"/>
<h:inputSecret converter="pwdConverter" id="password" value="#{sign.password}" required="true" requiredMessage="Введите пароль"/>
<h:commandButton action="#{sign.doLogin()}" value="Войти"/>
<h:commandLink action="/pages/register?faces-redirect=true" immediate="true" value="Зарегистрироваться"/>
</h:panelGrid>
<h:messages for="loginForm"/>
</h:form>
And it works fine: when I just click on the submit without input anything, it shows me a validation erros, but when I added a facebook-login button, I have a message in server log: Info: WARNING: FacesMessage(s) have been enqueued, but may not have been displayed.
sourceId=loginForm:email[severity=(ERROR 2), summary=(Введите e-mail), detail=(Введите e-mail)] for each field and validation messages not displayed on the page any more
there is how I added a fb-button:
<h:outputScript library="js" name="login.js"/>
<h:form id="loginForm">
<h:outputText value="Введите логин и пароль:"/>
<h:panelGrid columns="2">
<h:outputLabel for="email" value="E-Mail:"/>
<h:inputText id="email" value="#{sign.email}" required="true" requiredMessage="Введите e-mail" validatorMessage="email должен быть вида abc#abc.abc">
<f:validateRegex pattern="[\w\.-]*[a-zA-Z0-9_]#[\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]" />
</h:inputText>
<h:outputLabel for="password" value="Password:"/>
<h:inputSecret converter="pwdConverter" id="password" value="#{sign.password}" required="true" requiredMessage="Введите пароль"/>
<h:commandButton action="#{sign.doLogin()}" value="Войти"/>
<h:commandLink action="/pages/register?faces-redirect=true" immediate="true" value="Зарегистрироваться"/>
</h:panelGrid>
<h:messages for="loginForm"/>
</h:form>
<br/>
<div class="fb-login-button" data-max-rows="1" data-size="medium" data-show-faces="false" data-auto-logout-link="true"></div>
<div id="status"/>
enable/disable my selectOneRadio does not work like expected. It only activates after a "submit" and the ajax-direct approach does not work.
When I change the selection (click) to "Group", then the dropDown after the selection keeps being "disabled". It only appears after a "submit", but I like to have direct-ajax function.
<div>
<p:outputPanel id="customPanel" style="margin-bottom:10px">
<p:selectOneRadio id="locationType" value="#{bean.query.locationType}"
required="true" layout="custom">
<f:ajax render="locationGroup locationOrganization">
<f:selectItems value="#{bean.locationTypeSelectItems}"
var="locationTypeItem" itemValue="#{locationTypeItem}" itemLabel="#{msgs[locationTypeItem.label]}" />
</f:ajax>
</p:selectOneRadio>
<h:panelGrid columns="3" cellpadding="5">
<p:radioButton id="option1" for="locationType" itemIndex="0" />
<p:outputLabel for="locationGroup" value="Group"/>
<p:autoComplete id="locationGroup"
value="#{bean.query.locationGroup}"
completeMethod="#{bean.completeGroups}"
var="group"
itemLabel="#{group.description}"
itemValue="#{group}"
converter="org.company.project.presentation.group.GroupConverter"
maxResults="10"
dropdown="true"
cache="true"
disabled="#{bean.locationGroupDisabled}"/>
<p:radioButton id="option2" for="locationType" itemIndex="1" />
<p:outputLabel for="locationOrganization" value="#{msgs.pat_Organization}"/>
<p:autoComplete id="locationOrganization"
value="#{bean.query.locationOrganization}"
completeMethod="#{bean.completeOrganizations}"
var="organization"
itemLabel="#{organization.name}"
itemValue="#{organization}"
converter="org.company.project.presentation.organization.OrganizationConverter"
maxResults="10"
dropdown="true"
cache="true"
disabled="#{bean.locationOrganizationDisabled}"/>
<p:radioButton id="option3" for="locationType" itemIndex="2" />
<p:outputLabel value="All" />
</h:panelGrid>
<p:message for="locationGroup" />
<p:message for="locationOrganization" />
</p:outputPanel>
<p:message for="locationType" />
That's all folks!
I am new to JSF/Java in general but have been trying to solve this for a few days now.
I have a form which gets stuck on validation. When all the entries are valid, it all works well. The minute I break validation (such as don't provide a required value), then the form gets stuck. One thing that happens is I cant correct the invalid entry it seems and repost. Also, where I had a cascading ajax call of a selectOneMenu, that suddenly starts failing...even though this is not the invalidated part of the form.
I notice that the cascading drop down seems to be throwing null pointer exceptions in its overridden equals method.
I am at a loss.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:composition template="/templates/layout.xhtml">
<ui:define name="content">
<p:ajaxStatus onstart="statusDialog.show();" onsuccess="statusDialog.hide();"/>
<p:dialog modal="true" widgetVar="statusDialog" header="Status"
draggable="false" closable="false">
<p:graphicImage value="/resources/images/ajaxloadingbar.gif" />
</p:dialog>
<h:form id="form">
<p:panel id="panel"
header="Please ensure your personal details are accurate"
style="margin-bottom:10px;">
<p:messages id="msgs" />
<h:outputText
value="Please ensure your personal details are up to date and accurate within the Admin Direct system. Please note that this application only supports GMD customers, so unless you are within GMD, or are a user of the GMD Admin Direct service, please do not enter your details or attempt to use the application for administrative support." />
<h:panelGrid columns="3" cellpadding="5" id="grid">
<h:outputText value="First Name:" style="font-weight:bold" />
<p:inputText id="firstName"
value="#{personalDetailsBean.user.firstName}"
requiredMessage="First name is required..." style="width:250px" />
<p:message id="firstNameMessage" for="firstName" />
<h:outputText value="Last Name:" style="font-weight:bold" />
<p:inputText id="lastName"
value="#{personalDetailsBean.user.lastName}"
requiredMessage="Last name is required..." style="width:250px" />
<p:message id="lastNameMessage" for="lastName" />
<h:outputText value="Select Function:" style="font-weight:bold" />
<p:selectOneMenu id="functions"
value="#{personalDetailsBean.user.function}"
style="width:250px">
<f:selectItem itemLabel="Select Function" itemValue="" />
<f:selectItems value="#{personalDetailsBean.functions}" var="func"
itemLabel="#{func.functionName}" itemValue="#{func}" />
<f:converter converterId="functionConverter" />
</p:selectOneMenu>
<p:message id="functionMessage" for="functions" />
<h:outputText value="Select Site" style="font-weight:bold" />
<p:selectOneMenu id="sites"
value="#{personalDetailsBean.user.site}"
style="width:250px">
<f:selectItem itemLabel="Select Site" itemValue="" />
<f:selectItems value="#{personalDetailsBean.sites}" var="sit"
itemLabel="#{sit.siteName}" itemValue="#{sit}" />
<f:converter converterId="siteConverter" />
<p:ajax update="region" event="change" process="#this"/>
</p:selectOneMenu>
<p:message id="siteMessage" for="sites" />
<h:outputText value="Region" style="font-weight:bold" />
<h:outputText id="region"
value="#{personalDetailsBean.user.site.region.regionName}" />
<p:message id="regionMessage" for="region" />
<h:outputText value="Email" style="font-weight:bold" />
<p:inputText id="email" value="#{personalDetailsBean.user.email}"
required="true"
validatorMessage="Invalid email address format"
style="width:250px">
<f:validateRegex
pattern="[\w\.-]*[a-zA-Z0-9_]#[\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]" />
<f:validateLength minimum="2" />
</p:inputText>
<p:message id="emailMessage" for="email" />
</h:panelGrid>
<p:separator />
<p:commandButton value="Save" id="btnSubmit" actionListener="#{personalDetailsBean.saveUser}" process="#all" update="panel" />
</p:panel>
</h:form>
</ui:define>
</ui:composition>
</html>
any advice greatly appreciated.
Regards
SM
I'm trying to implement ajax client side validation with jsf 2.0 (primefaces).
I prefer onblur event rather than ontype, because it seems more user friendly. The problem is: my Register button has to be clicked twice to work correctly when a focus is inside an invalid field. 1st time we click - onblur event happens, 2nd time we click - submit happens (i suggest this is the reason). My code:
<html xmlns="http://www.w3c.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:composition template="template.xhtml">
<ui:define name="content">
<p:panel header="#{msg['register']}" style="width: 550px; align: left;">
<h:form>
<h:panelGrid columns="3" cellpadding="2">
<h:outputLabel for="name" value="#{msg['yourName']}:" />
<p:inputText id="name" value="#{userManagedBean.name}">
<f:validateLength maximum="20" />
<p:ajax update="msgName" event="blur" />
</p:inputText>
<p:message for="name" id="msgName" display="text"/>
<h:outputLabel for="userName" value="*#{msg['login']}:"/>
<p:inputText id="userName" value="#{userManagedBean.username}" label="UserName" required="true">
<f:validateLength minimum="5" maximum="20" for="userName"/>
<p:ajax update="msgUserName" event="blur"/>
</p:inputText>
<p:message for="userName" id="msgUserName"/>
<h:outputLabel for="password" value="*#{msg['password']}:" />
<p:password id="password" value="#{userManagedBean.password}" required="true">
<f:validator validatorId="confirmPasswordValidator" />
<f:attribute name="confirm" value="#{confirmPassword.submittedValue}" />
<f:ajax event="blur" execute="password confirm" render="m_password" />
</p:password>
<p:message id="m_password" for="password" />
<h:outputLabel for="confirm" value="*#{msg['retypePassword']}:" />
<p:password id="confirm" binding="#{confirmPassword}" required="true">
<f:ajax event="blur" execute="password confirm" render="m_password m_confirm" />
</p:password>
<p:message id="m_confirm" for="confirm" />
<h:outputLabel for="email" value="#{msg['email']}:"/>
<p:inputText id="email" value="#{userManagedBean.email}" label="email">
<f:validateRegex pattern="^([a-zA-Z0-9_\-\.]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$" for="email"/>
<p:ajax update="msgEmail" event="blur"/>
</p:inputText>
<p:message for="email" id="msgEmail"/>
</h:panelGrid>
<ui:remove><p:captcha label="Captcha"/> </ui:remove>
<h:commandButton type="submit" value="#{msg['register']}" action="#{userManagedBean.register}"></h:commandButton>
</h:form>
</p:panel>
</ui:define>
</ui:composition>
</html>