In CommandButton immediate="true" but validation not skipped? - jsf

I have added immediate="true" in button
<h:commandButton id="browse" action="#{creationBean.getATerminationRoot()}" value="Browse" immediate="true">
<rich:componentControl event="click" target="aTermPanel" operation="show" /></h:commandButton>
Now in same page i have included another page like below
<ui:insert name="name">
<ui:include src="../pages/abc.xhtml" />
</ui:insert>
This page have some validation in inputtextbox
<h:inputText id="ammOnDemandId" required="true"
value="#{var.amount}"
requiredMessage="Msg1"
validatorMessage="msg2">
<f:validateRequired />
<f:validateLongRange minimum="0" maximum="9999999">
</f:validateLongRange>
<rich:validator event="blur" />
</h:inputText>
Note:- This included page have another <h:form>
If i am removing these validation everything working fine in parent page and clicking on button data is loaded but when i am adding validation in this included page textbox button not working due to validation fail.

As far as i understand your h:commandButton trigger two things :
-> an http request which expecting a refresh or redirect of the page
-> an non-http action which shows up a new panel in the current page
Maybe jsf don't know how to deal with this contradiction.

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.

JSF commanbutton refreshes the page and popup menu disappears immediately

I am trying to show a popup menu in by checking some conditions, such as if something is not selected show popup etc. and if everyhing is fine submit the page. Here is the code:
<h:commandButton onclick="if (#{moneyTransferManager.showPopup()})
#{rich:component('popup')}.show();" value="Devam" >
<rich:componentControl target="popup" operation="show" />
</h:commandButton>
<rich:popupPanel id="popup" modal="false" autosized="true" resizeable="false">
<f:facet name="header">
<h:outputText value="Simple popup panel" />
</f:facet>
<f:facet name="controls">
<h:outputLink value="#" onclick="#{rich:component('popup')}.hide();
return false;">
X
</h:outputLink>
</f:facet>
<p>
The popup panel is open and closed from the javascript function of component client side object. The following code
hide this panel:
<f:verbatim>#</f:verbatim> #{rich:component('popup')}.hide()
</p>
</rich:popupPanel>
then after button is clicked, popup shows for like a second and then page is refreshed and popup is lost. To prevent refreshing page i tried:
<f:ajax execute="#form" render="#none" />
but then if everything is right and if i don't need a popup i need to submit the page by commandbutton, but since i say render=#"none" i cannot do this. So what can i do about this situation?
Thanks
<h:commandButton> has a default button type submit which submits enclosing h:form when it is clicked. That is why the page refreshes when you click.
<h:button> should be used for java script usage.In addition, <h:commandButton> becomes <h:button> if type attribute is set to button.
<h:button onclick="if (#{moneyTransferManager.showPopup()})
#{rich:component('popup')}.show();" value="Devam"/>
Or
<h:commandButton type="button" onclick="if (#{moneyTransferManager.showPopup()})
#{rich:component('popup')}.show();" value="Devam" >
See Also :
Difference between h:button and h:commandButton

Command buttons invokes actions on second push (jsf)

I came to strange behaviour of my application. Command buttons start to invoke actions on second hit. On first - nothing happens. It takes effect on firefox and chromium, but in epiphany works as usual.
My environment:
- ubuntu 11.04
- glassfish 3.1.1
- jsf 2.X
- primefaces 3.2
- firefox 12.0
- epiphany 2.30.6
Code example:
<ui:define name="content">
<h:form id="form">
<h:panelGrid id="panelGrid" columns="3">
<h:outputText value="#{msg.fieUserName}:"/>
<h:inputText id="name" value="#{userBb.editedUser.username}" />
<h:message for="name" styleClass="error_msg"/>
<h:outputText value="#{msg.fieUserDescription}:"/>
<h:inputText id="description" value="#{userBb.editedUser.description}" />
<h:message for="description" styleClass="error_msg"/>
<h:outputText value="#{msg.fieUserPassword}:"/>
<h:inputSecret id="password" value="#{userBb.editedUser.password}" redisplay="true"/>
<h:message for="password" styleClass="error_msg"/>
<h:outputText value="#{msg.fieUserRights}:"/>
<p:selectOneMenu id= "rights"
value= "#{userBb.editedUserGroup}"
converter="#{pGroupOfUsersConverter}">
<f:selectItems
value ="#{groupDao.findAll()}"
var ="row"
itemLabel="#{groupDao.rightsDescription(row.id)}"
itemValue="#{row.groupname}"
>
</f:selectItems>
</p:selectOneMenu>
<h:message for="rights" styleClass="error_msg"/>
<h:outputText value="#{msg.fiePorofolioName}:" rendered="#{userBb.chosenNew}"/>
<h:inputText id="portName" value="#{userBb.portfelForNewUser.nazwa}" rendered="#{userBb.chosenNew}">
<f:validateBean disabled="true" />
</h:inputText>
<h:message for="portName" styleClass="error_msg" rendered="#{userBb.chosenNew}"/>
<h:outputText value="#{msg.fiePotofolioCurrency}:" rendered="#{userBb.chosenNew}"/>
<p:selectOneMenu id= "waldep"
value= "#{userBb.portfelForNewUser.walutaDepozytowa}"
converter="#{igConverter}"
rendered= "#{userBb.chosenNew}"
>
<f:selectItems value= "#{igDao.waluty}"
var= "row"
itemLabel="#{row.nazwa}"/>
</p:selectOneMenu>
<h:message for="waldep" styleClass="error_msg" rendered="#{userBb.chosenNew}"/>
</h:panelGrid>
<h:panelGrid columns="2">
<h:commandButton value="#{msg.butCreate}" action="#{userBb.formCreate()}" rendered="#{userBb.chosenNew}" />
<h:commandButton value="#{msg.butSave}" action="#{userBb.formEdit()}" rendered="#{!userBb.chosenNew}"/>
<h:commandButton value="#{msg.butBack}" action="#{userBb.formBack()}"/>
</h:panelGrid>
</h:form>
</ui:define>
In this example method userBb.formCreate() is invoked only on second click on command button although button is visible. When fields are not properly filled up than appropriate messages appear next to them, but... only on second click! Any advice?
I check out points from: this advice, but not found solution.
Ok, I found what was wrong. So:
Appearance of the problem:
I've got a page for user data. Some input items and command buttons. When clicking "Create" button, input data is checked out. If data is ok user is created and table of users appears, or when there are errors - errors messages appear and user stays on the same page:
I found some erratic behavior. Nothing has happened on first click (action), only second and subsequent actions have an effect. But. This behavior was related to kind of web browser I use.
All actions takes place from the first click, in webrowsers: epiphany and konqueror. Although in firefox and chromium I observed this erratic behavior which I described above. Code for a command button was:
<h:commandButton value="#{msg.butCreate}" action="#{userBb.formCreate()}" rendered="#{userBb.chosenNew}"/>
Different behaviors in different webbrowsers.
The cause.
The cause was enumerated by #Balusc in his note, which I read roughly first time. It was indeed pt. 7.
The solution.
I've tried to change button declaration this way:
<h:commandButton value="#{msg.butCreate}" action="#{userBb.formCreate()}" rendered="#{userBb.chosenNew}">
<f:ajax render="userForm"/>
</h:commandButton>
where userForm was proper id of h:form. No result, still only second and subsequent clicks has an effect - shows error messages.
So I changed declaration command button from previous page, that invoked erratic behavior page. Originally it was:
<p:commandButton value="#{msg.butNew}" action="#{userBb.actionNew()}"/>
primefaces command button. And that was it, as Balusc wrote: "If a parent of the with the UICommand button is been rendered/updated by an ajax request beforehand, then the first action will always fail."
So I changed declaration to:
<p:commandButton value="#{msg.butNew}" action="#{userBb.actionNew()}" ajax="false"/>
And that's it. It works fine in any browser, for the first action.

JSF Authentication: cannot intercept error messages

I have developed a simple login form to be used in my JSF + PrimeFaces page:
<form action="j_security_check" method="post">
<p:dialog modal="true" header="Login" widgetVar="loginDlg">
<h:panelGrid columns="3" cellpadding="5">
<h:outputLabel for="j_username">Username:</h:outputLabel>
<h:inputText id="j_username" required="true" />
<h:message for="j_username" />
<h:outputLabel for="j_password">Password:</h:outputLabel>
<h:inputSecret id="j_password" required="true" />
<h:message for="j_password" />
<br />
<h:commandButton value="Login" />
</h:panelGrid>
</p:dialog>
</form>
Tried with an empty password, but the missing password (that is required) is not caught by h:message component. I have also switched to a p:commandButton thinking that the problem could have been in the Ajax behaviour of the button, but the page is not rendered because PrimeFaces complains about the CommandButton not being inside a form element. The exception thrown by the container is:
com.sun.enterprise.security.auth.login.common.LoginException: Login failed: Access denied on empty password for user pippo
To summarize, I have 2 questions:
Why the missing password doesn't produce a message before the form is submitted?
How can I catch a LoginException and display the error message inside the dialog?
The j_security_check request is handled by the web container, not by JSF. That explains that the required="true" won't work. It works only when you use JSF <h:form> and programmatic login by HttpServletRequest#login() in the action method associated with the command button.
Best what you can do is to confiure a <form-error-page> in web.xml pointing to the very same URL as the <form-login-page>. You could then check if the request has been forwarded by j_security_check itself, which would mean that a login error has occurred.
<h:panelGroup rendered="#{requestScope['javax.servlet.forward.servlet_path'] == '/j_security_check'}">
<h:outputText value="Unknown login, please try again" styleClass="error" />
</h:panelGroup>
Use this instead of the <h:message>.
As to why <p:commandButton> complains that there's no form is simply because you didn't use <h:form>.
Unrelated to the concrete problem, that <form> (or <h:form> whenever you would decide to switch to programmatic login) can better be placed in the body of <p:dialog>, not outside. The <p:dialog> can by JS be relocated to end of body which would cause it not to be in a form anymore.

Resources