update a bean property from the same jsf - jsf

i want update a bean property from the same jsf wo contains this bean property by getting the new value from a method inside this bean.
here is the jsf sample :
<h3>JSF Login Logout</h3>
<h:outputText value="Username" />
<h:inputText id="username" value="#{login.user}"></h:inputText>
<h:outputText value="Password" />
<h:inputSecret id="password" value="#{login.pwd}"></h:inputSecret>
<h:message for="password"></h:message>
<br /><br />
<h:commandButton action="#{login.validateUsernamePassword}"
value="Login"></h:commandButton>
here is the bean method :
//validate login
public String validateUsernamePassword() {
...
this.user = "admin";
...
}
i want return back to the same jsf and fill user field by the new value.

If you want to stay on the same page then you don't have to return String, just create void method. If you want to update fields after form submit you can do it in JSF component by ajax with render attribute and specify these fields with ID or by selectors like #form:
<h:commandButton action="#{login.validateUsernamePassword}" value="Login">
<f:ajax execute="formId" render="username otherComponentId"/>
</h:commandButton>
or update from backing bean:
public String validateUsernamePassword() {
...
this.user = "admin";
RequestContext.getCurrentInstance().update("formId:username"); //PrimeFaces solution since you have PrimeFaces tag on your question
...
}
Better option is to use render attribute and probably you would like to also update h:message for any occurred errors (give it ID and update it in render).
Difference between returning null and "" from a JSF action
Can I update a JSF component from a JSF backing bean method?
Render multiple components with f:ajax

Related

Log the number of submit button clicks though the form is invalid

I am trying to log the number of the button clicks.
1. Should log the number of clicks though the form is invalid. The field value1 in the form is integer. So, It shall also consider conversion errors.
2. Action to be done at backing bean
I have tried with listener on ajax.
<h:form id="form">
<h:inputText id="in" name="in" value="#{listenBean.value1}" autocomplete="off">
</h:inputText>
<h:commandButton value="Click Me" action="#{listenBean.save}">
<f:ajax execute="#form" render="#form message eventcount" />
</h:commandButton>
<h:message for="in"/>
Button Clicks: <h:outputText id="eventcount" value="#{listenBean.eventCount}"/>
</h:form>
Bean
public void eventCount(AjaxBehaviorEvent event) {
//increment the counter
}
public void save() {
//save
}
Issues:
The listener method is not called when the conversion errors on input field binded to integer at bean. I enter the value as "some text". During thsi time listener is not called.
Version: Mojaraa 2.2.8
Is this the correct way of doing. Am I doing any mistake.
Can some one help me.
The <h:outputText value> doesn't represent a method expression which should reference a bean (listener) method. It represents a value expression which should reference a bean property which will then be outputted as (escaped) text to the response.
Your best bet is to hook on preRenderView event of the component and check if the current request represents a postback request.
<h:form id="form">
<h:commandButton ...>
<f:ajax execute="#form" render="#form" />
</h:commandButton>
Button Clicks:
<h:outputText id="eventcount" value="#{listenBean.eventCount}">
<f:event type="preRenderView" listener="#{listenBean.incrementEventCount}" />
</h:outputText>
</h:form>
private int eventCount;
public void incrementEventCount(ComponentSystemEvent event) {
if (FacesContext.getCurrentInstance().isPostback()) {
eventCount++;
}
}
public int getEventCount() {
return eventCount;
}
Note that render="#form" covers the entire form already, so there's no need of specifying individual components inside the very same form. In case you've another ajax action inside the same form for which you'd like to not count the event, then make sure that render="..." is specific enough that it doesn't cover the eventcount component.

How to use <f:ajax> to set updated value in managed bean when value of <h:inputText> is changed

I have a JSF page with <h:inputText>. I want to set the value bound to the <h:inputText> when the value is changed.
Bean:
#ManagedBean
#SessionScope
public class MyBean {
private String in;
//getter and setter
}
View:
<h:inputText value="#{myBean.in}" />
How can I use <f:ajax> for this?
Just nest the <f:ajax> tag within the <h:inputText> tag.
<h:inputText value="#{myBean.in}">
<f:ajax />
</h:inputText>
It'll submit the value when the HTML DOM change event has occurred (i.e. when the field was edited and then blurred).
The event attribute already defaults to valueChange, so it's omitted. Its execute attribute already defaults to #this, so it's omitted. In case you'd like to update other component on complete, set render attribute. E.g.
<h:inputText value="#{myBean.in}">
<f:ajax render="msg" />
</h:inputText>
<h:message id="msg" />
If you want to invoke a listener when it has been successfully set, set the listener attribute:
<h:inputText value="#{myBean.in}">
<f:ajax listener="#{myBean.changeIn}" />
</h:inputText>
public void changeIn() {
System.out.println("in has been changed to " + in);
}
See also:
When to use valueChangeListener or f:ajax listener?
What values can I pass to the event attribute of the f:ajax tag?

Pass input text value to bean method without binding input value to bean property

Can I pass a input text field value to a bean method without binding the value to a bean property?
<h:inputText value="#{myBean.myProperty}" />
<h:commandButton value="Test" action="#{myBean.execute()} />
Can I do this without doing temporary save in #{myBean.myProperty}?
Bind the component as UIInput to the view and use UIInput#getValue() to pass its value as method argument.
<h:inputText binding="#{input1}" />
<h:commandButton value="Test" action="#{myBean.execute(input1.value)}" />
with
public void execute(String value) {
// ...
}
Note that the value is this way already converted and validated the usual JSF way.
See also:
How does the 'binding' attribute work in JSF? When and how should it be used?
JSF component binding without bean property
You can recover the parameters of the form by getting the Request and using plain Java EE ServletRequest#getParameter. When you use this method, remember to set the id and name of your components:
<h:form id="myForm">
<h:inputText id="txtProperty" /> <!-- no binding here -->
<input type="text" id="txtAnotherProperty" name="txtAnotherProperty" />
<h:commandButton value="Test" action="#{myBean.execute()} />
</h:form>
Managed Bean:
#ManagedBean
#RequestScoped
public class MyBean {
public void execute() {
HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
String txtProperty = request.getParameter("myForm:txtProperty");
//note the difference when getting the parameter
String txtAnotherProperty= request.getParameter("txtAnotherProperty");
//use the value in txtProperty as you want...
//Note: don't use System.out.println in production, use a logger instead
System.out.println(txtProperty);
System.out.println(txtAnotherProperty);
}
}
Another thread with more info:
Get request parameter values in JSF

JSF 2.0, messages not displayed inside a dataTable

I have a form with a dataTable which has various columns having links and outputTexts. There is one input field which is evaluated through an ajax request . A custom validator makes sure that only integers are added to the field. The form is below.
<form>
<h:dataTable var="item" value="#{listItems.model}" id="adminlistItems">
//other columns having commandLinks and outputTexts
<h:column>
<f:facet name="header" >
<h:outputText value="Quantity"/>
</f:facet>
<f:ajax listener="#{listItems.AddQuantityAction}">
<div style="padding:5px;float:left">
<h:inputText label="changeQuantity" id="addquantity" value="#{item.additionalQuantity}" maxlength="4" size="3">
<f:validator validatorId="integerValidator"/>
</h:inputText>
<h:outputText value=" "/>
<h:commandButton value="AddQuantity" />
<h:message for="addquantity"/>
</div>
</f:ajax>
</h:column>
</h:dataTable>
</h:form>
The code for the bean is :
#ViewScoped
#ManagedBean
public class ListItems implements Serializable {
//...
public String AddQuantityAction(){
//...
boolean result = //some action
FacesContext context=FacesContext.getCurrentInstance();
UIComponent component=UIComponent.getCurrentComponent(context);
String clientID=component.getClientId(context);
if (result) {
FacesMessage message = new FacesMessage("Quantity added successfully");
FacesContext.getCurrentInstance().addMessage(clientID, message);
} else {
FacesMessage message = new FacesMessage("Quantity not added.Processing error");
FacesContext.getCurrentInstance().addMessage(clientID, message);
}
return "adminListItems";
}
}
The custom validator throws a validator exception which is not displayed. And the listener also has code for messages which too are not displayed. I have read several similar questions and this sounds a common question too. But even if i am missing something obvious,i am in need of a third eye to see what i dont.
The execute and render of <f:ajax> defaults to #this. So only the currently active component will be processed and refreshed. When you press the button, this won't send the input value nor refresh the message component.
Fix it accordingly:
<f:ajax execute="addquantity" render="addquantity_message" listener="#{listItems.AddQuantityAction}">
...
<h:message id="addquantity_message" for="addquantity"/>
...
</f:ajax>
By the way, why don't you just use the builtin javax.faces.Integer converter instead of that validator?
<h:inputText ... converter="javax.faces.Integer">
Further, the return value of ajax listener methods should be void. It's totally ignored in any way. Also, method names should start with lowercase. See also Java naming conventions.
Update as per the comment, that didn't seem to work out well with regard to validation. The listener is invoked 2 times because essentially 2 ajax requests are been sent, one for the input and one for the command. I suggest to move the listener method to the <h:commandButton action>.
<f:ajax execute="addquantity" render="addquantity_message">
...
<h:commandButton action="#{listItems.AddQuantityAction}" />
<h:message id="addquantity_message" for="addquantity"/>
</f:ajax>
You'll only fix the obtained client ID to be the input ID, not the button ID.

How to pass parameter from a RequestScoped to a ViewScoped bean

I have a simple form where you can input a String. When submitting the form, the user is redirected to another page that echos the user input. The first page is using a RequestScoped bean whereas the second page is using a ViewScoped bean.
First Page:
<h:form>
Type a String: <h:inputText value="#{requestScopedBean.property}"></h:inputText>
<h:commandButton value="To View" action="#{requestScopedBean.toViewScopedBean}">
<f:setPropertyActionListener target="#{viewScopedBean.property}" value="#{requestScopedBean.property}" />
<f:ajax execute="#form" />
</h:commandButton>
</h:form>
Second Page:
This is the property passed by the requestScoped bean: <h:outputText value="#{viewScopedBean.property}"></h:outputText><br/>
This is the property created in the PostConstruct: <h:outputText value="#{viewScopedBean.otherProperty}"></h:outputText>
I understand why it does not work. When the form is submitted, the viewScopedBean.property is set to the correct value but then we switch to another view, so a new ViewScopedBean is created. That's why the value from the request is lost.
How do you pass the parameter from page one to page two without changing the scope of the bean?
Alternatively you could put the string on the request map when triggering the requestScopedBean action
public String toViewScopedBean(String string){
Map<String,Object> requestMap = FacesContext.getCurrentInstance().getExternalContext().getRequestMap();
requestMap.put("StringKey", string);
return "toViewScopedBean";
}
and then retrieve the value from the valueScopedBean
public String getProperty(){
Map<String, Object> requestMap = FacesContext.getCurrentInstance().getExternalContext().getRequestMap();
return (String) requestMap.get("StringKey");
}

Resources