I have a database table that contains data for several groups (It is football fixtures) and I want to display this in a JSF application.
I have JPA setup with a POJO for the database table and with a simple backing bean I can show everything in a single datatable.
This looks like
#Entity
#Getter #Setter #NoArgsConstructor
#Table(name="FIXTURES")
public class Fixture {
#Id
#Column(name="FIXTURE_ID")
private int fixtureId;
#Column(name="FIXTURE_DATE")
private Date fixtureDate
// more fields
}
Then
#Stateless
public class FixtureService {
#PersistenceContext(unitName="fixtureUnit")
private EntityManager em;
public void addFixture(Fixture fixture) {
em.persist(fixture);
}
public List<Fixture> getFixtures() {
return em.createQuery("From Fixture").getResultList();
}
// more stuff
}
and finally in the backing bean I have
#Inject
private FixtureService fixService;
public List<Fixture> getFixtures() {
return fixService.getFixtures();
}
What I would like however is split this up so I have separate tables for each group.
Using PrimeFaces I would like to do something like
<p:tabView>
<p:tab title="Group A">
<h1>Group A</h1>
<h:dataTable value="#{bean.fixtures}" var="f">
<h:column>
<f:facet name="header">Date</f:facet>
<h:outputText value="f.date" />
</h:column>
<h:column>
<f:facet name="header">Home Team</f:facet>
<h:outputText value="f.homeTeam" />
</h:column>
<!-- more columns -->
</p:tab>
</p:tabView>
and repeat with more columns and more groups.
I presume there is a way of dynamically creating the tabs based on which groups appear in the data but the main issue I am having is how (and where) I get the data for each group.
Currently I have it working so I return a list of fixtures but I am struggling to work out how I can just show group A's fixtures on that tab. Looking to understand how best I turn one big table into several smaller tables
I am using Weblogic 12.2.1.4 which is JSF 2.2
Related
I am wondering how to display a List<T> as obtained below in a Facelet:
public List<T> searchByString(String string) {
return getEntityManager().createNamedQuery("Userdetails.findByUsername").setParameter("username", "%" + string + "%").getResultList();
}
Would a <h:dataTable> be a suitable way?
You're going need to iterate over it. JSF 2 offers three iteration components out the box. Provided that the User entity look like below,
#Entity
public class User {
private #Id Long id;
private String username;
private String email;
private LocalDate birthdate;
// Add/generate getters+setters.
}
and that the search results are assigned as a List<User> users property of a bean which is available as #{bean},
#Named #RequestScoped
public class Bean {
private List<User> users;
// Add/generate postconstruct+getter.
}
here are some examples based on it:
<h:dataTable>, an UI component which generates a HTML <table>.
<h:dataTable value="#{bean.users}" var="user">
<h:column>#{user.id}</h:column>
<h:column>#{user.username}</h:column>
<h:column>#{user.email}</h:column>
<h:column>#{user.birthdate}</h:column>
</h:dataTable>
<ui:repeat>, an UI component which generates no HTML markup (so, you'd have to write all that HTML in the desired fashion yourself, which could easily be changed to e.g. <ul><li>, or <dl><dt><dd>, or <div><span>, etc):
<table>
<ui:repeat value="#{bean.users}" var="user">
<tr>
<td>#{user.id}</td>
<td>#{user.username}</td>
<td>#{user.email}</td>
<td>#{user.birthdate}</td>
</td>
</ui:repeat>
</table>
<c:forEach>, a tag handler which runs during view build time instead of view render time (background explanation here: JSTL in JSF2 Facelets... makes sense?), it also doesn't produce any HTML markup:
<table>
<c:forEach items="#{bean.users}" var="user">
<tr>
<td>#{user.id}</td>
<td>#{user.username}</td>
<td>#{user.email}</td>
<td>#{user.birthdate}</td>
</td>
</c:forEach>
</table>
See also:
Java EE 6 tutorial - Adding components to a page - using <h:dataTable>
How and when should I load the model from database for h:dataTable
You can save your List in a class variable, give it a getter and (maybe) a setter. Declare searchByString method as void and call it with let's say a (provided you are using PrimeFaces):
<p:commandLink update="#form" process="#this" action="#{myBean.searchByString}">
myBean:
public void searchByString(String string) {
userList = getEntityManager().createNamedQuery("Userdetails.findByUsername").setParameter("username", "%" + string + "%").getResultList();
}
provided your table sits in a form that you just updated you could display the List in it.
<p:dataTable var="user" value="#{myBean.userList}">
<p:column headerText="Name">
<h:outputText value="#{user.name}" />
</p:column>
</p:dataTable>
I'm editing data with <p:dataTable> row editor as below.
<p:dataTable value="#{bean.users}" var="user" editable="true">
<p:ajax event="rowEdit" listener="#{bean.onRowEdit}" />
<p:ajax event="rowEditCancel" listener="#{bean.onRowEditCancel}" />
<p:column>
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{user.firstName}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{user.firstName}" />
</f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
The backing bean is implemented as below.
private List<User> users;
#EJB
private UserService userService;
public List<User> getUsers() {
users = userService.list();
return users;
}
When I enter the new data in the cellEditor and submit it, they are not available in listener method. I noticed that they get overwritten by the data called from the database.
Why does this happen and how can I avoid it?
Your problem is caused by performing business logic in a getter method. Every iteration over the data table will invoke the getter method. So, while JSF is busy iterating over the data table in order to set the submitted values in the model, the getter calls returns a new list from DB again and again.
You're not supposed to perform business logic in a getter method. As long as you're a starter, you'd better refrain from touching the getter (and setter) methods and perform the job elsewhere in an one time called method.
You likely need a #PostConstruct (and a true service/DAO class) here:
private List<User> users;
#EJB
private UserService userService;
#PostConstruct
public void init() {
users = userService.list(); // Call the DB here.
}
public List<User> getUsers() {
return users; // Just return the already-prepared model. Do NOT do anything else here!
}
See also:
Why JSF calls getters multiple times
I want to create my own jsf tag to display a table grid for my project about online surveys. In the first row, there should be a title and a dynamic count of images (smileys). After first row, there should be questions and the same count of selectOneRadios like images. The result should be a table with a question column and dynamic columns for possible survey answers.
I think I need three loops. The first to display the images in the table header, the second to list all questions and the third loop to list all possible answers (or selectOneRadio) to each question. I tried to use the h:dataTable because this could loop over my questions but what's about the other dynamic data?
note: Because of our cms it's necessary that I only use jsf 1.2 components.
thanks for your help
yves beutler
If I got you right you want something like this:
In the JSP:
<h:dataTable value="#{myBean.questions}"
var="question">
<h:column>
<f:facet name="header" >
<h:outputText value="Question"/>
</f:facet>
<h:outputText value="#{question.title}"/>
</h:column>
<h:column>
<f:facet name="header" >
<!-- smilies go here -->
</f:facet>
<h:selectOneRadio>
<f:selectItems value="#{question.options}"/>
</h:selectOneRadio>
</h:column>
</h:dataTable>
In the Controller you would return a list of questions:
public List<Question> getQuestions(){
List<Question> questions = new ArrayList<Question>();
questions.add(new Question("How did you like this?"));
questions.add(new Question("How did you like that?"));
return questions;
}
and your question class may look something like this:
public class Question{
private final String title;
public Question(String title){
this.title = title;
}
public String getTitle(){
return title;
}
public List<SelectItem> getOptions(){
List<SelectItem> items = new ArrayList<SelectItem>();
items.add(new SelectItem("1", "Very much"));
items.add(new SelectItem("2", "okay"));
items.add(new SelectItem("3", "not that good"));
items.add(new SelectItem("4", "bad"));
return items;
}
}
I have a page with a data table. I want some of the items in the tables to be linked to a corresponding view page.
For example, right now I have a table with no links:
<h:dataTable var="bean" value="#{beanServiceImpl.beans}" border="1">
<h:column>#{bean.id}</h:column>
</h:dataTable>
I want to add hyperlinks to some entries and have them go to a view page showing them more info based on their id:
<h:dataTable var="bean" value="#{beanServiceImpl.beans}" border="1">
<h:column>
#{bean.id}
</h:column>
</h:dataTable>
ViewBean.xhtml will contain something like this:
ViewBean.xhtml
<ul>
<li>ID: #{bean.id}</li>
<li>Field 1: #{bean.field1}</li>
<li>Field 2: #{bean.field2}</li>
</ul>
How do I accomplish something like this in JSF? I know that I'll have to write a controller to query the id for the other fields. But how do I make viewBean.xhtml run the business logic to get the other fields and render it?
The BalusC's answer is almost good, but will not work (edit: it works now).
You already know, how to add the value to the params. BTW, if I were you, I would not use <a href>, but instead:
<h:link outcome='viewBean'>
<f:param name='id' value='#{bean.id}' />
</h:link>
Now you have to choices when it comes to catching the value. The simplest would be to add annotation above your id property:
#ManagedProperty("#{param.id}") // this will inject id from param into id
private Long id;
// (getters and setters are obligatory)
#PostConstruct // this will execute init() after id is injected
public void init() {
}
And the last thing: having a variable named "bean" has no more sense than calling it "variable" (or having a dog named Dog and cat named Cat). It carries no information and worse, it makes all the beans in your application indistinguishable (unless you build a legumes manager).
I'll assume JSF 2.x. Add this to your Bean
#ManagedProperty(value="#{param.id}")
private Long id;
(this does basically a bean.setId(request.getParameter("id")) whenever the view loads)
It'll be available in #PostConstruct method of Bean.
#PostConstruct
public void init() {
// Fill model based on id.
}
This is what I did.
<h:form>
<h:commandLink action="#{bean.populateBean}" value="#{bean.id}">
<f:setPropertyActionListener target="#{bean.id}" value="#{bean.id}" />
</h:commandLink>
</h:form>
In my Bean.java class, I added the action controller:
public String populateBean(){
Bean bean = BeanServiceImpl.getBean(id); //id was injected by the commandLink
this.field1 = tenure.getField1();
this.field2 = tenure.getField2();
return("viewBean");
}
My ViewBean.xhtml is the same:
<ul>
<li>ID: #{bean.id}</li>
<li>Field 1: #{bean.field1}</li>
<li>Field 2: #{bean.field2}</li>
</ul>
In JSF how do you pass a parameter from one page to another without using managed beans?
e.g.
<h:dataTable value="#{myObjects}" var="object">
<h:column>
<h:commandButton value="View Object" action="view-object"/>
</h:column>
</h:dataTable>
I want to pass the object so an the next page I can simply do #{object.displayValue}
Thxs.
First of all, you can't do this without using a managed bean.
The best approach would be using a DataModel as the value of the h:dataTable so that you can retrieve the currently selected row object by DataModel#getRowData(). You only need to ensure that the bean preserves the same model in the subsequent request. In other words, fill the model in the constructor of the bean.
<h:form>
<h:dataTable value="#{bean.model}" var="item">
<h:column>
<h:commandButton value="View Object" action="#{bean.view}"/>
</h:column>
</h:dataTable>
</h:form>
With a request (or session) scoped bean which look like this:
public class Bean {
private DataModel model;
private Item item;
public Bean() {
List<Item> list = new ArrayList<Item>();
list.add(new Item(1, "value1"));
list.add(new Item(2, "value2"));
list.add(new Item(3, "value3"));
model = new ListDataModel(list);
}
public String view() {
item = (Item) model.getRowData();
return "view";
}
public DataModel getModel() {
return model;
}
public Item getItem() {
return item;
}
}
I assume that you're using JSF 1.x and not 2.x yet, else a #ViewScoped bean was better.
And in the next page:
<p>#{bean.item.value}</p>