This question already has answers here:
How to populate options of h:selectOneMenu from database?
(5 answers)
Closed 6 years ago.
Up until now, I have always been using JSP to display pages. When a user request for a page such as "Add Item", I will load all Item Category in an Array List and display them as options in select box like this:
<select name="category>
<%
ArrayList<Category> categories = (ArrayList<Category>) request.getAttribute("categories");
for (Category c : data) {
%>
<option value="<%= c.getId() %>"><%= c.getName() %></option>
<%
}
%>
</select>
From the book "JavaServer Faces 2.0, The Complete Reference", I learnt that: "JSF enforces clean Model-View-Controller separation by disallowing the inclusion of Java code in markup pages". Hence, I'd be very grateful if someone could show me how I can handle the above task using JSF since I cannot use Java code as I have always done anymore.
Best regards,
James Tran
JSF 2.0 uses Facelets as the templating method, which in a nutshell is XHTML with some additional elements.
While technically you can perform method calls from Facelets, in general the idea is to access a JavaBean with proper geter/setter methods to perform your data moving. You can accomplish this as the below segment of code shows:
<h:selectOneMenu value="#{backingBean.selectedCategory}">
<f:selectItems value="#{backingBean.categoryList}"/>
</h:selectOneMenu>
On the bean side of things, you want to expose a bean to JSF using either faces-config (which is largely discouraged) or a mechanism such as CDI or the Managed Bean infrastructure. I highly recommend you look into using SEAM if you go the CDI route, as it will unify the (currently really strangely disparate) Managed Bean and CDI frameworks, so you can use JSF scopes in CDI, and have CDI beans available in JSF scopes.
#ManagedBean(name="backingBean")
#ViewScoped
public class MyJavaBackingBean {
#ManagedProperty("#{param.categories}")
protected List<String> categoryList
public void setSelectedCategory(String value) {
this.selectedCategory = value;
}
public String getSelectedCategory() {
return this.property;
}
...
}
You can also make the getters do lazy initialization of your values (for pulling categoryList from a database for example), and use some other JSF annotations to do various initialization tasks.
You can also code action methods which return a String representing the JSF action (this gets coded into your faces-context.xml file) to take after returning. Phase listeners on the backing bean can also be called at various stages of page rendering, validation and submission, getting you very fine grained control.
categoryList in the above example is not limited to basic types of course, and <f:selectItems> also has some syntax for writing out the textual version of your select items, so you can make some quite complex expressions to display each item in a friendly way.
Create a bean and make it known with e.g. #Named so you can refer to it from your JSF script. Then give that bean a method returning the data you want to show, and invoke that method from your JSF script in a location where that data is expected e.g. a loop construct.
Store the data you want to display in a Java list, and expose that list as a property of a backing bean. The use the appropriate JSF tag to display that property.
In JSF 2.0 you can include the tag h:selectOneMenu in which you get the value where you store the item value selected. The value in f:selectItems could be a collection of any object the most of times SelectItem in this object your declare value object and the label to display.
<h:selectOneMenu value="#{backingBean.selectedvalue}">
<f:selectItems value="#{backingBean.List}"/> </h:selectOneMenu>
if you required values and labels of another object in you must declare
<h:selectOneMenu value="#{backingBean.selectedvalue}">
<f:selectItems value="#{backingBean.ListCar}" var="car" itemLabel="#{car.model}" itemValue="#{car.modelId}"/>
</h:selectOneMenu>
Related
The main page has link to create new record and one to show all the existing records.
On the create_new_record page I am writing all the data to a file in an action class method called saveRecords and populating a List<Records> in retriveRecords methods.
My action class code:
public class MyRecordes{
List<RecoredInfo> recoreds= new ArrayList<RecoredInfo>();
}
I have getters and setters for the same records in my action class(I am using Struts 2),
but on the main page when I click to show all records (which shows a different JSP page), nothing is displayed. Do I have to use servlets and/or doGet, etc. methods?
EDIT:
Adding code for showList.jsp:
<table>
<s:iterator value="arrayList" status="status">
<tr>
<td><s:property value="firstName"/> <s:property value="lastName"/>
</td>
</tr>
</s:iterator>
</table>
My action class has an arraylist named arrayList and I am using getters/setters to set the value.
The different action will populate the list and return a result of the different JSP page. In the different JSP you can show records using
iterator
Iterator will iterate over a value. An iterable value can be any of:
java.util.Collection, java.util.Iterator, java.util.Enumeration,
java.util.Map, or an array.
Whatever you show on the JSP the data should be bound to the beans properties that you can retrieve via OGNL expression and written to the JSP output.
OGNL
OGNL is the Object Graph Navigation Language (see
commons-ognl for the full
documentation of OGNL). Here, we will cover a few examples of OGNL
features that co-exist with the framework. To review basic concepts,
refer to OGNL Basics.
If you are using Struts2 you don't need servlets and/or doGet etc. methods. Struts2 framework implements MVC pattern that you can follow while writing your web application. If you are new to the framework, then better get started from the Tutorials.
Tutorials
The framework documentation is written for active web developers and
assumes a working knowledge about how Java web applications are built.
For more about the underlying nuts and bolts, see the Key
Technologies Primer.
Is there a way to have a JSF Backing bean cause an update of a component on the page? I am not looking to use an ajax component with update attribute to update a component on the page. I need to trigger an update from within a JSF backing bean method. Note the update on the page can happen after this method completes or prior to its completion. I am using PrimeFaces, if there is a solution that can be had from using PrimeFaces.
Using standard JSF API, add the client ID to PartialViewContext#getRenderIds().
FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().add("foo:bar");
Using PrimeFaces specific API, use PrimeFaces.Ajax#update().
PrimeFaces.current().ajax().update("foo:bar");
Or if you're not on PrimeFaces 6.2+ yet, use RequestContext#update().
RequestContext.getCurrentInstance().update("foo:bar");
If you happen to use JSF utility library OmniFaces, use Ajax#update().
Ajax.update("foo:bar");
Regardless of the way, note that those client IDs should represent absolute client IDs which are not prefixed with the NamingContainer separator character like as you would do from the view side on.
I also tried to update a component from a jsf backing bean/class
You need to do the following after manipulating the UI component:
FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().add(componentToBeRerendered.getClientId())
It is important to use the clientId instead of the (server-side) componentId!!
The RequestContext is deprecated from Primefaces 6.2. From this version use the following:
if (componentID != null && PrimeFaces.current().isAjaxRequest()) {
PrimeFaces.current().ajax().update(componentID);
}
And to execute javascript from the backbean use this way:
PrimeFaces.current().executeScript(jsCommand);
Reference:
https://github.com/primefaces/primefaces/wiki/Migration-Guide
https://forum.primefaces.org/viewtopic.php?t=53129
Everything is possible only if there is enough time to research :)
What I got to do is like having people that I iterate into a ui:repeat and display names and other fields in inputs. But one of fields was singleSelect - A and depending on it value update another input - B.
even ui:repeat do not have id I put and it appeared in the DOM tree
<ui:repeat id="peopleRepeat"
value="#{myBean.people}"
var="person" varStatus="status">
Than the ids in the html were something like:
myForm:peopleRepeat:0:personType
myForm:peopleRepeat:1:personType
Than in the view I got one method like:
<p:ajax event="change"
listener="#{myBean.onPersonTypeChange(person, status.index)}"/>
And its implementation was in the bean like:
String componentId = "myForm:peopleRepeat" + idx + "personType";
PrimeFaces.current().ajax().update(componentId);
So this way I updated the element from the bean with no issues. PF version 6.2
Good luck and happy coding :)
In order to updte the component from backing bean, we can achieve as below
RequestContext.getCurrentInstance().update('updatePanelGroup');
<h:panelGroup id="updatePanelGroup">
.....
....
</h:panelGroup>
Updating the component differs with respect to prima face version.
This question already has answers here:
How to dynamically add JSF components
(3 answers)
Closed 7 years ago.
I'm writing an application that serves as an admin panel using JSF 2.0 and Hibernate. I have a JSP page with a JSF form which elements are added dynamically using javascript (jQuery to be specific). So I cannot make any assumption on how much data do I have to process. I have a managed bean but I don't know how to put the getters and setters for the dynamic fields that I want to save in a database. The solution seems to use a list rather than a single element but how do I use the value tag of the JSF element? Could it be something like this:
<h:form>
<h:inputText id="i1" value="#{UserBean.list}" />
<h:inputText id="i2" value="#{UserBean.list}" />
<h:commandbutton id="submit" value="Submit" action="#{UserBean.submit}"/>
</h:form>
And the managed bean:
#ManagedBean(name="UserBean")
#RequestScoped
public class UserBean {
public UserBean() {
List<String> list = null;
}
public List getList() {
return list;
}
public List setList(List<String> newlist) {
list = newList;
}
}
However, the above code does not seem correct and certainly does not work. I need to bind two or more values of the inputtext to the same list. Does anyone have any suggestions how to solve it? Thanks in advance.
Regards,
sass.
You can't directly add JSF components dynamically using jQuery. All jQuery can is traversing and manipulating "plain vanilla" HTML DOM tree at the client side. It has totally no notion of the JSF component tree as it is generated and maintained in the server side. JSF in turn knows nothing about the state changes in the HTML DOM tree done by "plain vanilla" jQuery/JavaScript since it doesn't notify JSF on the server side about the changes. JSF relies on the JSF component tree to process form submits, not the HTML DOM tree.
You want to change the JSF component tree dynamically using JSF. Since this is going to be a long story to explain in detail, here are some links to similar questions I answered before to get you started:
How to add JSF components dynamically - This should be exactly what you need.
How to create dynamic JSF form - This does it the "other way round", just in case you're interested.
You can use primefaces extension dynaform. where you can create form dynamic.
See this link
http://fractalsoft.net/primeext-showcase-mojarra/views/dynaForm.jsf
Modifying working form with one spot per order to multiple spots per order I met problems with prepopulating h:selectOneMenu. Exception is java.lang.IllegalArgumentException: Value binding '#{spot.deliveryTypes}'of UISelectItems with component-path {Component-Path : [Class: javax.faces.component.UIViewRoot,ViewId: /order.jsp][Class: javax.faces.component.html.HtmlForm,Id: pf][Class: javax.faces.component.html.HtmlSelectOneMenu,Id: _idJsp11][Class: javax.faces.component.UISelectItems,Id: _idJsp12]} does not reference an Object of type SelectItem, SelectItem[], Collection or Map but of type : null
old working JSP code:
<h:selectOneMenu value="#{order.deliveryType}" immediate="true">
<f:selectItems value="#{order.deliveryTypes}" />
</h:selectOneMenu>
new not working JSP code:
<c:forEach var="spot" items="${order.spots}">
<h:selectOneMenu value="#{spot.deliveryType}" immediate="true">
<f:selectItems value="#{spot.deliveryTypes}" /> <%-- Works as empty list if this line removed --%>
</h:selectOneMenu> <c:out value="${spot.name}"/><br/>
</c:forEach>
New field was introduced List<Spot> spots as well as getter and setter. List<SelectItem> getDeliveryTypes() has been moved from managed bean class Order to class Spot.
How to access to spot.deliveryTypes? Changing # to $ didn't help because value= doesn't accept EL.
MyFaces 1.1.8
Thanks.
JSTL and JSF doesn't go nicely hand in hand. The JSP won't be processed from top to bottom as you'd expect from the coding. It's more so that JSTL processes the JSP from top to bottom first and then hands the generated result over to JSF for its own processing from top to bottom. This makes especially the c:forEach unusable for this kind of requirements. In this particular case, the ${spot} won't be there anymore when it's JSF's turn to process the JSP page.
You'd like to use a JSF UIData based component instead of c:forEach. A fullworthy JSF alternative to the c:forEach is Tomahawk's t:dataList. Use it and your problem will be solved.
If it happens that you're using Facelets instead of JSP, you can also use its ui:repeat instead.
I would like to add buttons dynamically from a backing bean to a JSF page (supporting Rich Faces as well).
The value of the buttons needs to be determined in run time and returned to the backing bean when the button is pressed. (Hence the title - I am actually trying to be able to do something like "#{beans.run(3)}", i.e - set a fixed parameter to be used when clicking a button)
So for example, if the user creates a button (on run time) and gives the button a value. This value should be returned to the backing bean to be analysed.
My question - How do I assign a button (the button is a JSF component with a4j:support child) with a value at runtime? (I tried using a4j:actionParam, but couldn't manage to work it out)
P.S - I've overhauled this question to be shorter and more to the point from the original-too-long-question
There are a number of opions:
use JSF 2.0
use JBoss EL extension
use <f:setPropertyActionListener value="3" target="#{bean.propety>, where propety is later read by the run() method.
<h:commandButton action="#{bean.run}">
<f:setPropertyActionListener target="#{bean.property}"
value="#{pageVariable}" />
</h:commandButton>
<!-- pageVariable contains the number you are passing -->
public class Bean {
private int property; // with setters and getters
public void run() {
// do something with property
}
}
use Facelets functions (here's an example for such a function) (not applicable in all cases)