JSF 2.0 - Ajax submit validation on inputs - jsf

I have a form that needs to be submitted with ajax. I am trying to get the validation to work but it wont work when I use ajax. When I take the ajax out and submit the form with an empty testinput it properly triggers he validation and does not submit the form. How can I do this with an ajax call. My form is below.
<h:form>
<f:ajax>
<h:panelGrid columns="3">
<h:outputLable for=test" value="testinput:" />
<h:inputText id=test" required="true" label="testinput" />
<h:message for="test" id="testError"/>
</h:panelGrid>
<h:commandButton value="Submit" actionListener="#{testBean.doSomething}" />
</f:ajax>
</h:form>

The <f:ajax> by default doesn't re-render the form, so you won't see anything. Replace <f:ajax> by <f:ajax execute="#form" render="#form" />.

Maybe try something like this:
<h:form id="yourFormId">
<!-- form content -->
<h:commandButton value="Submit">
<f:ajax execute="yourFormId" listener="#{testBean.doSomething}"/>
</h:commandButton>
</h:form>

Related

JSF component is not rendered from my p:commandButton in in a dialog in included page

My page contains a login header that i include via ui:include. The included page contains a dialog with a p:commandButton. When the user logs in, the include page is refreshed properly according to the #form in the update attribute. I also want to update a component outside the included page, that shall display a button when the user is logged in. The include page refreshes and the name of the logged in user is displayed. But the button in the main page is not shown. It is displayed if I refresh the page though. I can't figure out what I'm doing wrong here. Anyone have any ideas.
The header page also displays the commandLink component properly. But when clicking the logout link, the button in the main page is not removed. Since the commandLink does not use ajax, I assume that a normal page POST is done. Which should reload the whole page. Doesn't this work from a page that have been referenced with ui:include?
The login page is using a session scoped backing bean. The main page is view scoped.
Here's the included xhtml (login.xhtml):
<ui:composition
xmlns="http://www.w3.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:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<div style="width:100%;font-size:12px;line-height:20px;background-color:#b0d9e6;color:white">
<h:form>
<h:message id="top_msg"></h:message>
<h:panelGrid width="100%" columns="3" columnClasses="none,right1,right1">
<h:outputLink rendered="#{!loginController.loggedIn}" styleClass="text-align:right;" value="javascript:void(0)" onclick="PF('dlg').show();" title="login">
<p:outputLabel>Login</p:outputLabel>
</h:outputLink>
<h:commandLink rendered="#{loginController.loggedIn}" action="#{loginController.logout}" styleClass="text-align:right;" >
<h:outputLabel>Logout</h:outputLabel>
</h:commandLink>
<p:growl id="growl" sticky="true" showDetail="true" life="3000" />
<p:dialog header="Login" widgetVar="dlg" resizable="false">
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel for="username" value="Username:" />
<p:inputText id="username" value="#{loginController.username}" required="true" label="username" />
<h:outputLabel for="password" value="Password:" />
<p:password id="password" value="#{loginController.password}" required="true" label="password" />
<f:facet name="footer">
<p:commandButton value="Login"
update="#form :createform:createbutton"
actionListener="#{loginController.login}"
oncomplete="handleLoginRequest(xhr, status, args)" >
</p:commandButton>
</f:facet>
</h:panelGrid>
</p:dialog>
</h:panelGrid>
<script type="text/javascript">
function handleLoginRequest(xhr, status, args)
</script>
</h:form>
</div>
</ui:composition>
...
This one is included in the following main page:
...
<ui:include src="login.xhtml" />
<h:form id="createform">
<h:panelGroup id="createbutton" layout="block">
<p:commandButton id="createnew"
ajax="false"
action="#{recepieController.createNewRecipes}"
value="Create new recipe"
rendered="#{recepieController.loggedIn and !recepieController.create and !recepieController.viewOnly and !recepieController.edit}"
accesskey="s">
</p:commandButton>
</h:panelGroup>
</h:form>
You cannot rerender a non-rendered component. If you partially render a button, and the button is not rendered, you cannot call an update on that button, because it does not exist in the DOM.
You have to call the AJAX update on the parent naming container, that is ALWAYS rendered. Thus, update the :createform rather than the button inside. The form is always rendered, no matter what.
I found the issue. In my commandButton "createnew", I used the wrong value to render on.
<p:commandButton id="createnew"
ajax="false"
action="#{recepieController.createNewRecipes}"
value="Create new recipe"
rendered="#{recepieController.loggedIn and !recepieController.create and !recepieController.viewOnly and !recepieController.edit}"
accesskey="s">
</p:commandButton>
It should use my session scoped bean (loginController) to check if the user is logged in. Changing to the following works.
<h:panelGroup id="createbutton">
<p:commandButton id="createnew"
ajax="false"
action="#{recepieController.createNewRecipes}"
value="Create new recipe"
rendered="#{loginController.loggedIn and !recepieController.create and !recepieController.viewOnly and !recepieController.edit}"
accesskey="s">
</p:commandButton>
</h:panelGroup>
Note the difference rendered="#{loginController.login ...} instead of rendered="#{recepieController.loggedIn}"
The recepieController also has a loggedIn attribute which I set, but since the page is not re-posted I guess the value is not changed for the attribute when I login.
However, I believe I tested to use ajax="false" in the p:commandButton for the login dialog which I guess should reset the view scoped version of my loggedIn attribute. I don't fully understand why that didn't work.

URL parameters lost after JSF validation

I have a requirement where I need to display the header and footer based upon the value in the URL parameters. Everything works fine. But the URL params are lost after JSF validations. This happens only when I click submit. Works fine for the ajax validations.
<h:panelGrid columns="1" id="lnamePanel">
<h:inputText tabindex="1" maxlength="50" id="lastName" value="#{registrationBean.last_name}" required="true" requiredMessage="Last Name is a required field" validatorMessage="Not a valid last name">
<f:validateRegex pattern="^[A-Za-z-_.\s]{2,50}$"/>
<f:ajax event="blur" render="lnamePanel" />
</h:inputText>
<h:message for="lastName" display="text" style="color:red;"/>
</h:panelGrid>
<h:commandButton value="Submit" actionListener="#{registrationBean.handleSubmit}" ajax="true"/>
How do I retain the url parameters after JSF validation? In this case, I cannot manipulate the URL inside the backing bean as the backing bean method is not getting called.
Any help would be appreciated.

<h:commandButton> is not refreshing page after actioned

hi we are using along with a4j tag.
here we are retrieving data from database after a click of button. even though the data is available in server, it will not display over view. After manual refresh of web page will lead to data diplay.
here is code snippet
.... some code here
<rich:tab id="menu5" label="Recall">
<ui:include src="/pages/mctrans/reCallMcifTrans.xhtml" />
</rich:tab>
reCallMcifTrans.xhtml contains below code
<h:commandButton type="button" id="reCallbutton1" value=" Search "
styleClass="commandExButton">
<a4j:support event="onclick" id="ajsf12"
oncomplete="javascript:alert('Search Completed');javascript:document.body.style.cursor='default';"
action="#{mcifRecallTransBean.reCallSearch}" reRender="reCallgrid1" />
</h:commandButton>
It looks like you're working with RichFaces 3.3. So, you don't need a <h:commandButton with <a4j:support> because you can use <a4j:commandButton> that already does this. You can refactor your code to this:
<a4j:commandButton type="button" id="reCallbutton1" value="Search"
styleClass="commandExButton"
action="#{mcifRecallTransBean.reCallSearch}"
reRender="reCallgrid1"
oncomplete="javascript:alert('Search Completed');javascript:document.body.style.cursor='default';" />
Make sure your reCallgrid1 component is available in the same <h:form> of the <a4j:commandButton>.
Since you also want to add a Wait while searching the data behavior when the button is clicked, you can use <a4j:status> along with the <a4j:commandButton> as shown in the <a4j:status> demo. Here's a basic example:
<a4j:commandButton type="button" id="reCallbutton1" value="Search"
styleClass="commandExButton"
action="#{mcifRecallTransBean.reCallSearch}"
reRender="reCallgrid1" />
<!-- Note that there's no oncomplete in this case -->
<a4j:status for="reCallbutton1">
<f:facet name="start">
<h:graphicImage value="/res/images/wait.gif"/>
</f:facet>
</a4j:status>
At last but not least, you should switch your managed bean to request scope and use RichFaces powerful <a4j:keepAlive> in order to simulate JSF 2 #ViewScoped. You can even use it in form of annotation on your managed bean (no additional configuration):
#KeepAlive
public class McifRecallTransBean {
//managed bean code here...
}
When you are using request parameters inside the bean, you need to pass them again with your action :
<h:commandButton type="button" id="reCallbutton1" value="Search" styleClass="commandExButton">
<a4j:support event="onclick" id="ajsf12" oncomplete="javascript:alert('Search Completed');javascript:document.body.style.cursor='default';" action="#{mcifRecallTransBean.reCallSearch}" reRender="reCallgrid1" />
<f:param name="param1" value="#{param['param1']}" />
<f:param name="param2" value="#{param['param2']}" />
</h:commandButton>

Single JSF form on a page approach vs several forms?

Does it makes sense to merge these several hidden forms on a single page into just one single big form?
To submit a particular set of parameters belonging to a particular form process attribute could be used to submit all elements required to be processed.
What are the pro/cons of this single form approach over using several forms?
<span class="hiddenForms">
<h:form>
<h:inputHidden id="selctdChnlType_in" value="#{channelCntlr.type}"/>
<h:inputHidden id="selctdChnlId_in" value="#{channelCntlr.channelId}"/>
<p:remoteCommand name="updateChnlDataPanel" process="#form" actionListener="#{channelCntlr.init()}" update=":channelHeader, :channelDataPanel, :channelSideColumn"/>
</h:form>
<h:form>
<h:inputHidden id="selctdLOBId_in" value="#{lobCntlr.targetLOBId}"/>
<p:remoteCommand name="updateLOBPanel" process="selctdLOBId_in, #this" actionListener="#{lobCntlr.retrieveCurrentLOB()}" update=":lobFullContentPanel" />
</h:form>
<h:form id="lobAction_form" >
<h:inputText id="targetLOBId_in" value="#{lobCntlr.targetLOBId}"/>
<h:inputText id="targetResponseId_in" value="#{lobCntlr.targetResponseOrCommmentId}"/>
<h:inputText id="targetAction_in" value="#{lobCntlr.targetAction}"/>
<p:remoteCommand name="doLOBAction" process="targetLOBId_in, targetAction_in, targetResponseId_in,#this" actionListener="#{lobCntlr.doLOBAction()}"/>
<h:inputText id="targetTopics" value="#{lobCntlr.list}" converter="listConverter"/>
<p:remoteCommand name="suggestAsHotLOB" process="targetLOBId_in, targetTopics, #this" actionListener="#{lobCntlr.addForTryAsHotLOB()}"/>
</h:form>
<h:form id="comment_form" >
<h:inputText id="targetLOBId_in" value="#{lobCntlr.targetLOBId}"/>
<h:inputText id="targetCommentOrResponseId_in" value="#{lobCntlr.targetResponseOrCommmentId}"/>
<h:inputText id="comment_in" value="#{lobCntlr.text_input}" required="true">
<f:validateLength minimum="15" maximum="1000"/>
</h:inputText>
<h:inputText id="previousCommenters_in" value="#{lobCntlr.list}" converter="listConverter"/>
<p:remoteCommand name="addComment" process="#form" actionListener="#{lobCntlr.addUserComment()}" oncomplete="addCommentToPage(args);" />
<p:remoteCommand name="deleteComment" process="targetLOBId_in, targetCommentOrResponseId_in, #this" actionListener="#{lobCntlr.removeUserComment()}" oncomplete="removeFromPage(args);" />
</h:form>
<h:form id="recosForm">
<h:inputText id="startFromRecos_in" value="#{recmdnsCntlr.startFromIndex}"/>
<p:remoteCommand name="fetchAllRecos" actionListener="#{recmdnsCntlr.retrieveAllRecmmndns()}" process="startFromRecos_in,howManyRecos_in,isLocalStorAvailble_in,#this" />
<p:remoteCommand name="fetchFollowiesList" actionListener="#{recmdnsCntlr.fetchAllFollowiesList()}" process="#this" oncomplete="storeFollowiesList(args)"/>
</h:form>
<span id="editsForm" style="display:none">
<form action="javascript:void(0);" class="edits_submitter" >
<p:inputTextarea styleClass="editedText"/>
<input type="submit" value="Save edits"/>
<a class="cancel-edit" href="javascript:void(0)">Cancel</a>
</form>
</span>
</span>
A major con to the single, monolithic JSF form control is the sheer volume of data that is (needlessly) sent to the server for processing. Using your existing code. Consider the following. If all the controls in <h:form id="lobAction_form" > and <h:form id="comment_form" > were in a single form, you'd have
<h:inputText id="targetLOBId_in" value="#{lobCntlr.targetLOBId}"/>
<h:inputText id="targetResponseId_in" value="#{lobCntlr.targetResponseOrCommmentId}"/>
<h:inputText id="targetAction_in" value="#{lobCntlr.targetAction}"/>
<p:remoteCommand name="doLOBAction" process="targetLOBId_in, targetAction_in, targetResponseId_in,#this" actionListener="#{lobCntlr.doLOBAction()}"/>
<h:inputText id="targetTopics" value="#{lobCntlr.list}" converter="listConverter"/>
<p:remoteCommand name="suggestAsHotLOB" process="targetLOBId_in, targetTopics, #this" actionListener="#{lobCntlr.addForTryAsHotLOB()}"/>
<h:inputText id="targetLOBId_in" value="#{lobCntlr.targetLOBId}"/>
<h:inputText id="targetCommentOrResponseId_in" value="#{lobCntlr.targetResponseOrCommmentId}"/>
<h:inputText id="comment_in" value="#{lobCntlr.text_input}" required="true">
<f:validateLength minimum="15" maximum="1000"/>
</h:inputText>
<h:inputText id="previousCommenters_in" value="#{lobCntlr.list}" converter="listConverter"/>
<p:remoteCommand name="addComment" process="#form" actionListener="#{lobCntlr.addUserComment()}" oncomplete="addCommentToPage(args);" />
<p:remoteCommand name="deleteComment" process="targetLOBId_in, targetCommentOrResponseId_in, #this" actionListener="#{lobCntlr.removeUserComment()}" oncomplete="removeFromPage(args);" />
</h:form>
For every command action that you initiate in that form, possibly to process 1 input text component, you'd always be sending all 13 components in there to the server anyway. Wasteful and unnecessary. You'll have high volume of client-server communications for small operations and sometimes slow response times. Depending on whatever JSF framework you're using, you might be able to get creative with this situation, selectively processing components and what not, but that is just needless and painful. Clean separation of concerns also comes into play in the presentation layer.
Then there is the problem of validation. More often than not, you will have selected components in a single form that are marked as required and have nothing to do with the rest of the components within that form. You'll most likely be unable to selectively process those components without affecting all the other components on that form.
I see you're using primefaces. You could consider the use of Wizard component. With this component there is a single form with more sections in different tabs. The validation is done in Ajax mode when you go from one tab to the next one. As the partial validation is done with Ajax, only the fields of the tab you are validating, are processed and sent to the server.
It is also useful to split long forms in more readable and user friendly sections.

How can we use multiple <h:messages> tags or <h:message> tags in a single JSF page?

My problem is that I have 2 forms in a single JSF page each having its <h:message> or <h:messages> tag. As we know the message/messages tags print any validation errors, so what happens is, suppose I leave the fields of any of the 2 forms empty it should print "Fields cannot be left blank" or some kind of message. It gives this message, but it gives twice as there are two forms. So I see the same error/validation message at each of the two forms.
So what I need is the <h:messages> or the <h:message> tag should display error/validation message only once for each of their respective forms!!
So any help would greatly be appreciated!!
If you're using JSF 2, then you could just submit and update the form by ajax. This allows for partially updating the view.
<h:form>
<h:messages />
...
<h:commandButton ...>
<f:ajax execute="#form" render="#form" />
</h:commandButton>
</h:form>
<h:form>
<h:messages />
...
<h:commandButton ...>
<f:ajax execute="#form" render="#form" />
</h:commandButton>
</h:form>
Or if you can't/don't want to use ajax for some unobvious reason, or are still using the legacy JSF 1.x, then check in the rendered attribute of <h:messages> if the desired form is been submitted or not.
<h:form binding="#{form1}">
<h:messages rendered="#{form1.submitted}" />
...
<h:commandButton ... />
</h:form>
<h:form binding="#{form2}">
<h:messages rendered="#{form2.submitted}" />
...
<h:commandButton ... />
</h:form>
The <h:message> shouldn't have this problem by the way, in contrary to what you're implying in your question.

Resources