How can I reload the same page from a managedBean in JSF? - jsf

Im implementing a login in a JSF application and have a problem with the redirection.
I want to make available the login form in every xhtml in the app, but after the login success or fail I want to keep the user in the same page they were when clicked on login.
I have tried to return null in the managedBean methong but that doesnt work because it not refreshes the webPage, I need the page to be refreshed for the view logic to work.
This is the login form:
<h:form id="loginForm" rendered="#{!loginBean.estaLogueado()}">
<p:panel header="#{msg.header_login}">
<h:outputLabel for="login" value="#{msg.login}"/>
<p:inputText id="login" value="#{loginBean.usuario}"></p:inputText><br/>
<h:outputLabel for="pwd" value="#{msg.password}"/>
<p:inputText id="pwd" type="password" value="#{loginBean.password}"></p:inputText><br/>
<p:commandButton action="#{loginBean.login()}" value="Login"/>
</p:panel>
</h:form>
<h:form id="logoutForm" rendered="#{loginBean.estaLogueado()}">
Bienvenido #{loginBean.nombreUsuario}!!<br/>
<p:commandButton action="#{loginBean.logout()}" value="Desconectar"/>
</h:form>
And this is the method in the action attribute:
public String login(){
currentUser = gu.login(usuario, password);
return null;
}
There is a way to return to the xhtml where the user loged, not being a fixed xhtml like "login.xhtml"??

Just redirect to the request URI.
public void login() throws IOException {
// ...
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ec.redirect(((HttpServletRequest) ec.getRequest()).getRequestURI());
}

As far as i am concern there is 2 ways for this purpose.
You should define the components which need to be updated in update attribute of caller commandButton.
You should do a real refresh by adding ?faces-redirect=true to return value of action.
First solution.
<h:form id="loginForm" rendered="#{!loginBean.estaLogueado()}">
<p:panel header="#{msg.header_login}">
<h:outputLabel for="login" value="#{msg.login}"/>
<p:inputText id="login" value="#{loginBean.usuario}"></p:inputText><br/>
<h:outputLabel for="pwd" value="#{msg.password}"/>
<p:inputText id="pwd" type="password" value="#{loginBean.password}"></p:inputText><br/>
<p:commandButton action="#{loginBean.login()}" value="Login" update=":loginForm :logoutForm"/>
</p:panel>
</h:form>
<h:form id="logoutForm" rendered="#{loginBean.estaLogueado()}">
Bienvenido #{loginBean.nombreUsuario}!!<br/>
<p:commandButton action="#{loginBean.logout()}" update=":loginForm :logoutForm" value="Desconectar"/>
</h:form>
the update attribute will update the components.
Second solution
Add ?faces-redirect=true to your return value of action method for a real refresh
public String login(){
currentUser = gu.login(usuario, password);
return "login?faces-redirect=true";
}

Related

How to reset inputText field in JSF Primefaces

InputText field in the following dialog retains previous value even though I set it to blank before calling show(). The inputText field is only displayed blank when show() is called for the first time. My bean is session scoped.
<p:dialog id="dlgId" widgetVar="dlgVar" dynamic="true">
<h:form>
<h:panelGrid columns="1">
<h:outputLabel for="nametext" value="Name" />
<p:inputText id="nametext" value="#{myBean.name}" />
</h:panelGrid>
<p:commandButton value="Save" actionListener="#{myBean.saveAction}" />
</h:form>
public void add(TreeNode selectedTreeNode) {
setName("");
RequestContext.getCurrentInstance().execute("PF('dlgVar').show()");
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
How can I get the inputTEext field to display the value I set before calling show() rather then the value previously entered by the user?
The thing is: you need to update your form. To make it, you can use one of these solutions.
Solution 1 : update it from your xhtml
<h:form id="form">
<h:panelGrid columns="1">
<h:outputLabel for="nametext" value="Name" />
<p:inputText id="nametext" value="#{myBean.name}" />
</h:panelGrid>
<p:commandButton value="Save" actionListener="#{myBean.saveAction}" update=":form" />
</h:form>
Solution 2 : update it from your managedBean
YourXhtml
<h:form id="form">
...
</h:form>
YourManagedBean
public void saveAction() {
...
name = "";
RequestContext.getCurrentInstance().update(":form");
}
You can also read this post Can I update a JSF component from a JSF backing bean method?.
Solution 3 : update it using an Ajax event
You can also add an ajax event
<p:commandButton value="Save" type="button" >
<p:ajax event="click" listener="#{myBean.saveAction}" update=":form"/>
</p:commandButton>

h:selectBooleanCheckbox always pass false to validator

I have h:selectBooleanCheckbox but it passes 'false' to the validator. always.
<h:panelGroup id="tncPanel">
<label>
<h:selectBooleanCheckbox id="tncSelection" value="#{businessBean.tncSelection}">
<f:validator validatorId="checkboxValidator"/>
<f:attribute name="label" value="Please agree terms and conditions."/>
</h:selectBooleanCheckbox>
I have read and agreed to all the
<a href="#" data-toggle="modal" data-target="#modal-term-and-conditions">
Terms and Conditions.
</a>
</label>
</h:panelGroup>
<h:panelGroup id="buttonPanel">
<h:commandLink id="nextButton" action="#{businessBean.goNext}">
Submit
</h:commandLink>
</h:panelGroup>
Why I have panelGroup here is, based on logic in top of page, I have a logic to display/not the button and checkbox
This is my Validator.
#FacesValidator("checkboxValidator")
public class CheckboxValidator implements Validator {
private static final String DEFAULT_LABEL = "Please confirm the address.";
#Override
public void validate(FacesContext context, UIComponent component, Object value){
String checkBoxValue = String.valueOf(((HtmlSelectBooleanCheckbox) component).getSubmittedValue());
System.out.println("checkBoxValue " + checkBoxValue);
System.out.println("value2: " + value);
String label = String.valueOf(component.getAttributes().get("label"));
if ("null".equals(label)) {
label = DEFAULT_LABEL;
}
if("false".equalsIgnoreCase(checkBoxValue)){
FacesMessage msg = new FacesMessage(null, label);
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(msg);
}
}
}
Validator sysout always prints checkBoxValue false
UPDATE
After comment on Balusc, I add another sysout to print directly the parameter value. But still it's printing as value2: false.
There is a bug related to this situation , When you render a container that holds a from from another form you the rendered form loses its view state ,Thus form is submitted to no destination solution is to render the form container and the form its self from the other form
For example that won't work :
<h:panelGroup id="panel">
<h:form>
<h:commandButton value="Submit" rendered="#{not testAction.flag}">
<f:ajax render=":panel" listener="#{testAction.submit()}"/>
</h:commandButton>
</h:form>
<h:panelGroup id="panel">
<h:form id="secondForm" rendered="#{testAction.flag}">
<h:selectBooleanCheckbox id="checkBox" value="#{testAction.boolVal}">
<f:validator validatorId="checkboxValidator"/>
</h:selectBooleanCheckbox>
<h:commandButton value="Go" action="#{testAction.go()}"/>
</h:form>
</h:panelGroup>
Second form submit will be like this :
secondForm won't have its view state the form is submitted but with no destination on the server cuz the view object is not fetched on the server that requires the javax.faces.ViewState value to be fetched by what you have to do here is to render form as well in the f:ajax:
<f:ajax render=":panel :secondForm" listener="#{testAction.submit()}"/>
That inform server to backup the second form rendered with the javax.faces.ViewState
Refer to that post : Rendering other form by ajax causes its view state to be lost, how do I add this back? for more info
Hope that was the problem :)

Empty page after h:commandButton submit

I have an JSF 2.2 page which contain forms and a <h:commandButton> to call the method, after the submit button, the method called successfully and all instructions works fine
Problem:
After the button submit, I got an empty page and the URL in the browser is still unchanged
What I want is that after the submit, the page stays the same and shows a growl message.
managedBean.java
#ManagedBean(name="consignmentShipBean")
#ViewScoped
public class ConsignmentShipBean implements Serializable{
public void send(){
//some instructions to do
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage("Successful", "__") );
}
}
page.xhtml
<p:growl id="growl" globalOnly="true" autoUpdate="true"/>
<h:form>
...
<h:commandButton value="Send" actionListener="#{consignmentShipBean.send}" />
</h:form>
UPDATE
the result after the button submit:
You have to perform an Ajax request, not an usual request. Use a standard button or a PrimeFaces one for it:
<h:commandButton value="Send" actionListener="#{consignmentShipBean.send}" >
<f:ajax update="growl"/>
</h:commandButton>
Or
<p:commandButton value="Send"
actionListener="#{consignmentShipBean.send}" update="growl" />

Google reCaptcha in JSF response g-recaptcha-response null

I'm trying to use Google ReCaptcha in my jsf project.
I've successfully render the gui like this:
<h:form id="contact-form" class="contact-form">
<p:panelGrid styleClass="submitGrid" columns="2">
<div class="g-recaptcha" data-theme="dark" data-sitekey="my-site-Key"></div>
<p class="contact-submit">
<p:commandButton id="contact-submit" styleClass="submit" value="Send" action="#{questionaryBean.validation()}" update="contact-submit,confirmDlg, contact-form" oncomplete="PF('dlg').show()"/>
</p>
</p:panelGrid>
</h:form>
And here's my backing bean:
public void save(){
Map<String,String> requestParams = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
requestParams.get("reportKey");
for(String key:requestParams.keySet()){
System.out.println("key:"+key+" value:"+requestParams.get(key));
}
}
As you can see, I printed all of the request parameters, but I can't see g-recaptcha-response here. And of course if I use String gRecaptchaResponse=requestParams.get("g-recaptcha-response"); ,the String gRecaptchaResponse is null.
Am I doing something wrong?

<p:focus> after page submit while staying on the same page does not work

I would like to use the Primefaces p:focus tag on a page that contains a form with input fields. Until the first commit the focus is set correctly. If I submit the form via a p:commandButton and return to the same page to show the error result (using FacesMessage messages), the focus is not defined (in Firefox the cursor blinks in the middle of nowhere).
How can I achieve a defined state of the focus? Can I choose which element has the focus after a submit?
Here are some code details:
The JSF page:
<p:panel header="Login">
<h:form>
<p:focus for="usernameInput" />
<p:panelGrid columns="2">
<p:outputLabel for="usernameInput">User name</p:outputLabel>
<p:inputText id="usernameInput" value="#{loginBean.username}" />
<p:outputLabel for="passwordInput">Password</p:outputLabel>
<p:password id="passwordInput" value="#{loginBean.password}" />
</p:panelGrid>
<p:commandButton value="Login" action="#{loginBean.login}" />
</h:form>
</p:panel>
<div>
<p:messages id="messages" globalOnly="false" autoUpdate="true" showDetail="true" showSummary="true" closable="false" />
</div>
The relevant parts of the Java class:
public String login() {
FacesContext fc = FacesContext.getCurrentInstance();
HttpServletRequest req =
(HttpServletRequest) fc.getExternalContext().getRequest();
try {
req.login(username, password);
return "/home?faces-redirect=true";
} catch (ServletException e) {
fc.addMessage(
null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error",
"error message")));
}
return null;
}

Resources