f:ajax validation shows only one message at once - validation

I'm working on JSF form with field validation.
<h:form>
<h:panelGrid id="panel" styleClass="data_table_pricing" columns="3">
<h:outputText value="Title"/>
<h:inputText id="title" value="#{pricingForm.title}" validatorMessage="Value is too big.">
<f:validateLength minimum="0" maximum="40" />
<f:ajax event="change" render="#form"/>
</h:inputText>
<h:message id="title_message" for="title" style="color:red"/>
<!-- // -->
<h:outputText value="First name"/>
<h:inputText id="first_name" value="#{pricingForm.firstName}" validatorMessage="Value is too big.">
<f:validateLength minimum="0" maximum="40" />
<f:ajax event="change" render="#form"/>
</h:inputText>
<h:message id="first_name_message" for="first_name" style="color:red"/>
<!-- // -->
<h:outputText value="Last name"/>
<h:inputText id="last_name" value="#{pricingForm.lastName}" validatorMessage="Value is too big.">
<f:validateLength minimum="0" maximum="40" />
<f:ajax event="change" render="#form"/>
</h:inputText>
<h:message id="last_name_message" for="last_name" style="color:red"/>
<!-- // -->
</h:panelGrid>
<h:commandLink value="reset" class="link" type="reset" style="margin: 20px;">
<f:ajax execute="#form" render="#form"/>
</h:commandLink>
<h:commandLink value="Next" class="link" style="margin: 20px;" actionListener="#{pricingForm.calculatorPage()}">
<f:ajax execute="#form" render="#form"/>
</h:commandLink>
</h:form>
When I insert into several input fields big values I see only one error message. Looks like when the form is rendered the old values are not saved. San you help me to solve this?

This,
<f:ajax event="change" render="#form"/>
means the same as: "when the value of the current input is changed, submit and process only the current input and update the whole form".
So, other inputs aren't processed/validated, and the update basically clears out previous messages.
You likely meant to update only the associated message. E.g. in case of your first input:
<f:ajax render="title_message" />
I only omitted event="change" as that's the default already in <h:inputXxx> components.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes

Related

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.

jsf messages enqueued and not display

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"/>

JSF Ajax not submitting

I have the following JSF code in my page
<h:panelGroup id="rSelectionPanel" rendered="#{bean.admin}">
<h4 class="header-line">Admin Panel</h4>
<h:panelGroup rendered="#{bean.selectionMode=='RS'}">
<h:form styleClass="registerForm">
<h:outputLabel value="End Line1?" rendered="#{not bean.endLine2}"></h:outputLabel>
<h:selectBooleanCheckbox id="endLine1" value="#{bean.endLine1}" rendered="#{not bean.endLine2}">
<p:ajax event="change" update=":rSelectionPanel"></p:ajax>
</h:selectBooleanCheckbox>
<h:outputLabel value="End Line2?" rendered="#{not bean.endLine1}"/>
<h:selectBooleanCheckbox id="endLine2" value="#{bean.endLine2}" rendered="#{not bean.endLine1}">
<p:ajax event="change" update=":rSelectionPanel"></p:ajax>
</h:selectBooleanCheckbox>
<h:inputTextarea id="newLine2Name" styleClass="form-poshytip" title="Line2 Name" rows="1" maxlength="50"
value="#{bean.newLine2Name}" validatorMessage="Too many characters" rendered="#{bean.endLine2}">
<f:passThroughAttribute name="placeholder" value="Line2 Name" />
<f:validateLength maximum="50" />
</h:inputTextarea>
<h:commandButton styleClass="submit" value="Select Line" action="#{bean.confirmLineBy}">
</h:commandButton>
</h:form>
</h:panelGroup>
</h:panelGroup>
With the following backing bean java code
public void confirmLineBy(){
getLog().debug("Entering confirmLineBy....");
ConfirmLineByRequest request = new ConfirmLineByRequest();
request.setPage(getPage());
request.setEndLine1(endLine1);
if(isEndLine2())request.setNewLine2Name(newLine2Name);
request.setEndLine2(isEndLine2());
ConfirmLineByResponse response = LineService.confirmLineBy(request, null);
nextUnconfirmedLines.removeAll(nextUnconfirmedLines);
setConfirmedLines(response.getConfirmedLines());
setLine2s();
setAddedLine(false);
getLog().debug("CONFIRMED LINES SIZE: "+confirmedLines.size());
getLog().debug("Exiting confirmLineBy....");
}
When clicking the commandButton with neither of the boxes checked, it submits fine. But when checking either of the checkboxes, it doesn't even call bean.confirmLineBy().
Any ideas?
Changed from using to . sorted now.

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" />

How to re-render <ui:repeat> using <f:ajax render>

I have implemented a list created by a repeater:
<ui:repeat value="#{projectData.paginator.list}" var="project">
<h:outputText value="#{project.title}" />
</ui:repeat>
and a Button that filters my list:
<h:commandLink action="#{overviewController.filterNew}">
<h:outputText value="Filter List" />
</h:commandLink>
So, is there an easy way to render only my repeater after clicking the command link (with AJAX) :-)
I tried following:
<f:ajax render="repeater">
ui:repeat id="repeater" value="#{projectData.paginator.list}" var="project">
<h:outputText value="#{project.title}" />
</ui:repeat>
<f:ajax />
<h:commandLink action="#{overviewController.filterNew}">
<h:outputText value="Filter List" />
<f:ajax event="click" render="repeater"/>
</h:commandLink>
but that did not work..
Update
<h:form>
ui:repeat id="repeater" value="#{projectData.paginator.list}" var="project">
<h:outputText value="#{project.title}" />
</ui:repeat>
<h:commandLink action="#{overviewController.filterNew}">
<h:outputText value="Filter List" />
<f:ajax event="click" render="repeater"/>
</h:commandLink>
</h:form>
doesn't work either... Maybe I hav to put the action method (overviewController.filterNew) into the ajax tag?
Update 2
<f:ajax event="click" render="repeater">
<h:commandLink action="#{overviewController.filterEBus}">
<h:outputText value="EBusiness" />
</h:commandLink>
</f:ajax>
Doesn't work either!
Maybe it's not possible to rerender a repeater ? is there another element like a div tag or something that can be rerendered???
...
Thank you for your help
The <ui:repeat> itself does not generate any HTML to the output. The <f:ajax render> expects an ID which is present in the HTML DOM tree. Put it in a <h:panelGroup> with an id and reference it instead.
<h:form>
<h:panelGroup id="projects">
<ui:repeat value="#{projectData.paginator.list}" var="project">
<h:outputText value="#{project.title}" />
</ui:repeat>
</h:panelGroup>
<h:commandLink action="#{overviewController.filterNew}">
<h:outputText value="Filter List" />
<f:ajax execute="#form" render="projects" />
</h:commandLink>
</h:form>
Yes:
using Richfaces <a4j:commandButton reRender="targetId" />
using JSF 2.0 <f:ajax event="click" render="targetId">
using Primefaces <p:ajax>
<f:ajax render="repeater">
ui:repeat id="repeater" value="#{projectData.paginator.list}" var="project">
<h:outputText value="#{project.title}" />
</ui:repeat>
<f:ajax />
why did you wrap it with f:ajax? It's redundant in this case.
Make sure that your components are surrounded by <h:form> tag
<h:form>
<ui:repeat id="repeater" value="#{projectData.paginator.list}" var="project">
<h:outputText value="#{project.title}" />
</ui:repeat>
<h:commandLink action="#{overviewController.filterNew}">
<h:outputText value="Filter List" />
<f:ajax event="click" render="repeater"/>
</h:commandLink>
</h:form>
How about this:
<ui:repeat id="repeater" value="#{projectData.paginator.list}" var="project">
<h:outputText value="#{project.title}" />
</ui:repeat>
<h:commandLink>
<h:outputText value="Filter List" />
<f:ajax render="repeater" listener="#{overviewController.filterNew}" />
</h:commandLink>

Resources