I'm working on a State-City Dropdown based on ajax requests in JSF 2.0. The thing is that i want to reuse this jsf module (beans and xhtmls) for future implementations.
Is there any solution that make it easy to the parentBean retrieve the id from a dropdown that is implemented in another file ?
The first solution that it came in my head was using ui:include but i'm experiencing null value at the variable that store the final selected option.
Here is the snippet. The basic structure is:
StateCityBean (Ajax Menu controller)
stateCityBean.xhtml (Ajax Menu)
ParentBean (selectedCity variable is used here)
parentBean.xhtml (ui:include to stateCityBean.xhtml is here)
stateCityBean
#ManagedBean(name = "stateCityBean")
#ViewScoped
public class StateCityBean implements Serializable {
private static final long serialVersionUID = 7344375121014662582L;
private static final Logger LOG = Logger.getLogger(MenuEstadoCidadeBean.class);
private Collection<SelectItem> stateList;
private Collection<SelectItem> stateCity;
private String selectedState; //not used yet, test purpose
private Integer selectedCity; //not used yet, test purpose
//All the code here is perfectly fine. Cities are loading based on the selected state in parentBean.
}
stateCityBean.xhtml
<t:subform id="stateCitySelectMenu">
<span class="label tamanho20">STATE:</span>
<span aria-live="polite">
<h:selectOneMenu class="tamanho10" id="stateList" name="stateList" value="#{bean.selectedState}" title="State">
<f:selectItems value="#{stateCityBean.stateList}" />
<f:ajax event="valueChange" render="CityList" listener="#{stateCityBean.searchCities(bean.selectedState)}" onevent="loadingGif"/>
</h:selectOneMenu>
</span>
<span class="tamanho20">CITY:</span>
<span aria-live="polite">
<h:selectOneMenu class="tamanho20" title="City" id="CityList" name="CityList" value="#{bean.selectedCity}">
<f:selectItems value="#{stateCityBean.cityList}" />
</h:selectOneMenu>
</span>
</t:subform>
parentBean.xhtml
<ui:include src="stateCityBean.xhtml">
<ui:param name="bean" value="#{parentBean}" />
</ui:include>
parentBean.java
#ManagedBean
#RequestScoped
public class parentBean implements Serializable {
private static final long serialVersionUID = -874412419784226660L;
private static final Logger LOG = Logger.getLogger(parentBean.class);
String selectedState;
Integer selectedCity;
public String getSelectedState() {
return selectedState;
}
public void setSelectedState(String selectedState) {
this.selectedState = selectedState;
}
public Integer getSelectedCity() {
return selectedCity;
}
public void setSelectedCity(Integer selectedCity) {
this.selectedCity= selectedCity;
}
public void doSomethingWithTheSelectedCityId(){
//bla bla bla
return "anotherPage"
}
}
Ok. I solved the problem.
Apparently was the s
at stateCity.xhtml i removed:
<t:subform id="stateCitySelectMenu">
And that's it.
Related
I would like to pass an value to a managed bean under the hood. So I have this managed bean:
#ManagedBean(name = "mbWorkOrderController")
#SessionScoped
public class WorkOrderController {
// more attributes...
private WorkOrder workOrderCurrent;
// more code here...
public WorkOrder getWorkOrderCurrent() {
return workOrderCurrent;
}
public void setWorkOrderCurrent(WorkOrder workOrderCurrent) {
this.workOrderCurrent = workOrderCurrent;
}
}
It holds a parameter workOrderCurrent of the custom type WorkOrder. The class WorkOrder has an attribute applicant of type String.
At the moment I am using a placeholder inside my inputtext to show the user, what he needs to type inside an inputText.
<p:inputText id="applicant"
value="#{mbWorkOrderController.workOrderCurrent.applicant}"
required="true" maxlength="6"
placeholder="#{mbUserController.userLoggedIn.username}" />
What I want to do, is to automatically pass the value of mbUserController.userLoggedIn.username to mbWorkOrderController.workOrderCurrent.applicant and remove the inputText for applicant completely from my form.
I tried to use c:set:
<c:set value="#{mbUserController.userLoggedIn.username}" target="#{mbWorkOrderController}" property="workOrderCurrent.applicant" />
But unfortunatelly I get a javax.servlet.ServletException with the message:
The class 'WorkOrderController' does not have the property 'workOrderCurrent.applicant'.
Does anybody have an advice?
The class 'WorkOrderController' does not have the property 'workOrderCurrent.applicant'.
Your <c:set> syntax is incorrect.
<c:set value="#{mbUserController.userLoggedIn.username}"
target="#{mbWorkOrderController}"
property="workOrderCurrent.applicant" />
You seem to be thinking that the part..
value="#{mbWorkOrderController.workOrderCurrent.applicant}"
..works under the covers as below:
WorkOrderCurrent workOrderCurrent = mbWorkOrderController.getWorkOrderCurrent();
workOrderCurrent.setApplicant(applicant);
mbWorkOrderController.setWorkOrderCurrent(workOrderCurrent);
This isn't true. It works under the covers as below:
mbWorkOrderController.getWorkOrderCurrent().setApplicant(applicant);
The correct <c:set> syntax is therefore as below:
<c:set value="#{mbUserController.userLoggedIn.username}"
target="#{mbWorkOrderController.workOrderCurrent}"
property="applicant" />
That said, all of this isn't the correct solution to the concrete problem you actually tried to solve. You should perform model prepopulating in the model itself. This can be achieved by using #ManagedProperty to reference another bean property and by using #PostConstruct to perform initialization based on it.
#ManagedBean(name = "mbWorkOrderController")
#SessionScoped
public class WorkOrderController {
#ManagedProperty("#{mbUserController.userLoggedIn}")
private User userLoggedIn;
#PostConstruct
public void init() {
workOrderCurrent.setApplicant(userLoggedIn.getUsername());
}
// ...
}
Perhaps you could explain the context a bit more, but here's another solution. If you're navigating from another page, you can pass some identifier of work WorkOrder in the URL, like this http://host:port/context/page.xhtml?workOrderId=1.
Then, you can set the identifier in the managed bean like this:
<h:html>
<f:viewParam name="workOrderId" value="#{mbWorkOrderController.id}"/>
</h:html>
You'll have to add a new property to your bean:
public class WorkOrderController {
private long id;
public long getId() { return id; }
public void setId(long id) { this.id = id; }
// ...
}
And then, after the property has been set by JSF, you can find the work order in a lifecycle event:
<h:html>
<f:viewParam name="workOrderId" value="#{mbWorkOrderController.id}"/>
<f:event type="preRenderView" listener="#{mbWorkOrderController.findWorkOrder()}"/>
</h:html>
public class WorkOrderController {
private long id;
public long getId() { return id; }
public void setId(long id) { this.id = id; }
public void findWorkOrder() {
this.workOrderCurrent = null /* some way of finding the work order */
}
// ...
}
This strategy has the advantage of letting you have bookmarkable URLs.
I added an <p:inputSwitch> in my JSF page, but this is not working.
Get and set method is not called when I change the stat
The JSF page :
<p:inputSwitch value="#{SystemController.statSystem}" />
The managed bean
#ManagedBean
#ViewScoped
public class SystemController extends AbstractController implements Serializable {
private Boolean statSystem;
public Boolean getStatSystem() {
return statSystem;
}
public void setStatSystem(Boolean statSystem) {
this.statSystem=statSystem;
}
I added an ajax tag and it works ! Get and Set methods are working now.
<p:inputSwitch value="#{SystemController.statSystem}" >
<p:ajax />
</p:inputSwitch>
Your statSystem variable is not initialized.
Init like:
private Boolean statSystem = false;
or instead change data type to primitive:
private boolean statSystem;
I'm working on a JSF Project using a Wildfly 8 Server and jsf 2.2.
I've a web part with xhtml and beans + ejb part with models etc and a mysql database.
Part of Model (EJB part): Foo.java
String name = "";
Object Foo2 = new Foo2();
Part of Model (EJB part): Foo2.java
private static final long serialVersionUID = 1L;
String name = "";
Now I've input like this: input.xhtml
<f:metadata>
<f:event listener="#{ InputBean.init() }" type="preRenderView" />
</f:metadata>
<h:inputText
value="#{ InputBean.actualFoo.name }">
</h:inputText>
<h:selectOneMenu
value="#{InputBean.currentSelectedFoo2_ID}">
<f:selectItems value="#{InputBean.lhm_AllFoo2}" />
</h:selectOneMenu>
and a bean: InputBean.java
#SessionScoped
#ManagedBean(name = "InputBean")
public class InputBean implements Serializable
private static final long serialVersionUID = 1L;
private Long currentSelectedFoo2_ID;
private LinkedHashMap<String, Object> lhm_AllFoo2;
private Foo actualFoo;
public InputBean() {
lhm_AllPermissions = new LinkedHashMap<String, Object>();
actualFoo = new Foo();
}
public void init()
// Method of interface in EJB part which gives me all Foo2 to a list
List<Foo2> list_AllFoo2 = foo2Interface.getAllFoo2;
if ((list_AllFoo2 != null) && (list_AllFoo2.size() > 0)) {
for (Foo2 foo2 : list_AllBFoo2) {
lhm_AllFoo2.put(foo2.getName(), foo2.getId());
}
}
When I input data in the inputField and select data the selectonemenu and then reload the page (f5) or change to another page (of the same project) and go back the data in the input field is still avaiable but the selectonemenu is reseted to the default value.
I tried to debug the problem, but the data is already lost when the init is accessed, no setter of the bean is called before. The constructer isn't called too, so everything seems to be correct. The bean data which isn't linked to an input isn't lost too.
Is this a normal JSF problem and is there a way to solve that?
I'm using a <rich:datatable> to show the content of a List<Map<String, String>
In the code below, spotlightPtBindings is the List<Map<String, String> and spotlightbinding represents each Map<String, String>. In the first column, I'm showing one selectBooleanCheckBox for eah row. When a selectBooleanCheckBox is checked, I'd like to send the value of the Map<String, String> corresponding to the key "URI" as a parameter to the method: inserirBean.onSelectedCheckBox(uri), and that's why I put this value in a ui:param of name: uri. The problem here is that when I try to print the value uri received in inserirBean.onSelectedCheckBox(uri), I don't get the any output, as if it is empty. Below there's the rest of the code:
InsereDocumento.xhtml
<rich:dataTable value="#{inserirBean.spotlightPtBindings}" var="spotlightbinding">
<rich:column>
<f:facet name="header">*</f:facet>
<ui:param name="uri" value="#{spotlightbinding['URI']}"/>
<h:selectBooleanCheckbox value="#{selectionBean.selected}" />
<c:if test="#{selectionBean.selected}">
#{inserirBean.onSelectedCheckBox(uri)}"
</c:if>
</rich:column>
<c:forEach items="#{inserirBean.variableNamesPt}" var="vname">
<rich:column>
<f:facet name="header">#{vname}</f:facet>
#{spotlightbinding[vname]}
</rich:column>
</c:forEach>
</rich:dataTable> <br />
SelectionBean
package managedBeans;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
#ManagedBean
public class CheckBoxSelectionBean implements Serializable {
private transient boolean selected = false;
private static final long serialVersionUID = 1L;
public CheckBoxSelectionBean() {
// TODO Auto-generated constructor stub
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
}
InserirBean - I'm not showing here how the List<Map<String, String>> named spotlightPtBinding and how the List<String> variableNamesPt were populated, because it was a complex process, but I can tell you they are certainly populated, cause I can see their content on the screen.
#ManagedBean
public class InsereDocumentoBean implements Serializable {
private static final long serialVersionUID = 1L;
private List<String> variableNamesPt = new ArrayList<String>();
private List<Map<String, String>> spotlightPtBindings = new ArrayList<Map<String, String>>();
public List<String> getVariableNamesPt() {
return variableNamesPt;
}
public List<Map<String, String>> getSpotlightPtBindings() {
return this.spotlightPtBindings;
}
public void onSelectedCheckBox(String uri) {
System.out.println("URI: " + uri);
}
}
What may the problem be? Thank you! I'm new to JSF and need your help!
In JSF rendering is a two-step process: there's view build time and view render time.
Although they're in the same file, some tags take effect at view build time, some at render time.
JSTL tags like <c:forEach>, <c:if> and all tag handlers (including <ui:param>, see here) are evaluated at view build time, they add content to the "final" xml tree that is then rendered by JSF.
JSF HTML tags and derivates like <rich:dataTable> are evaluated at view render time, so the datatable's var is evaluated later then the <ui:param> which causes spotlightbinding not to be bound when it's assigned to uri.
Instead, I suggest you assign an ajax listener to call the function:
<h:selectBooleanCheckbox value="#{selectionBean.selected}">
<f:ajax listener="#{inserirBean.onSelectedCheckBox(spotlightbinding['URI'])}" />
</h:selectBooleanCheckbox>
Note that the listener is called whenever the value changes.
In RichFaces 4.1, rich:progressBar 'currentValue' from the ManagedBean does not updating with for-loop.
progressBar.xhtml
<h:form id="formProgress">
<h:commandLink action="#{progressBarBean.startProcess}" value="click here"/>
<rich:progressBar mode="ajax" value="#{progressBarBean.currentValue}" interval="1000" id="pb"
enabled="#{progressBarBean.enabled}" minValue="0" maxValue="100">
<h:outputText value="Retrieving #{progressBarBean.currentValue} of #{progressBarBean.totalRecords}" />
</rich:progressBar>
</h:form>
Bean
package ap;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class ProgressBarBean implements Serializable {
private static final long serialVersionUID = 8775622106408411357L;
private boolean enabled = false;
private Integer totalRecords;
private Integer currentValue;;
public String startProcess() {
setEnabled(true);
setTotalRecords(100);
return null;
}
public Integer getCurrentValue() {
if (isEnabled()) {
for(currentValue=0;currentValue < totalRecords;) {
currentValue++;
}
}
return currentValue;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public Integer getTotalRecords() {
return totalRecords;
}
public void setTotalRecords(Integer totalRecords) {
this.totalRecords = totalRecords;
}
}
When i click the 'click here' link, the currentValue updates very fastly and reaches the totalRecords to 100 suddenly. It was not updating in the incremental way(present value in for-loop). The progress bar is not updated by the present value return by the method.
Any help please.
There are two problems: your Java code does not do what you want it to do and you're not telling the page to update (that won't happen automatically).
Take a look at the getCurrentValue() again: It increments currentValue from 0 to 100 and returns the result which is 100. #{progressBarBean.currentValue} does not care (or know) what happens with the variable, it only cares about the result of the getCurrentValue() method.
So in order for it all to work it will have to look like this:
Page
<a4j:commandLink action="#{progressBarBean.startProcess}" value="click here" render="pb" execute="#this"/>
<rich:progressBar mode="ajax" value="#{progressBarBean.currentValue}" interval="1000" id="pb"
enabled="#{progressBarBean.enabled}" minValue="0" maxValue="100">
<a4j:ajax event="begin" listener="#{progressBarBean.increment}" render="text"/>
<h:outputText value="Retrieving #{progressBarBean.currentValue} of #{progressBarBean.totalRecords}" id="text" />
</rich:progressBar>
The a4j:ajax is fired each second (i.e. each interval), it increments the currentValue and updates the text.
You also need a4j:commandLink (or a4j:ajax inside the h:commandLink) in order to rerender the progressbar - in your example you enable the progressbar in the bean but the value on the page does not change.
Bean
public Integer getCurrentValue() {
return currentValue;
}
public void increment() {
if (isEnabled() && currentValue < totalRecords) {
currentValue++;
}
}
Ask if anything isn't clear.