JSF: display dynamic values within dataTable or panelGrid - jsf

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;
}
}

Related

How do I split data into groups with JSF

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

How to bind List of List in jsf datatable

Hi I have a variable like
List<List<MyObject>> x = new ArrayList<List<MyObject>>();
I wanted this bind to a datatable in jsf which contains select
<datatable>
<column>
<Select/>
</column>
</datatable>
Is this possible in jsf
Code:
view.xhtml
<h:dataTable id="i1" value="#{bean.listoflist}" var="list1">
<h:column>
<h:selectOneListbox value="#{bean.somestring}" >
<f:selectItems value="#{list1.?}" var="any" itemValue="#{any.??}/>"
</h:selectOneListbox>
</h:column>
</h:dataTable>`
Bean.java (name = "bean")
public class Bean implements Serializable
{
List<List<MyObject>> listoflist = new ArrayList<List<MyObject>>()
//--------------Getters and Setter
}
MyObject.java
public class MyObject
{
private String s1;
private String s2;
//---------------getter and setter
}
If I understood your problem properly, you want to make a datatable of select elements whose options come form the nested list of your model. If yes, here is the solution:
prepare an array of selected elements per the size of the outer list;
have a converter for your model object;
fill the UI components accordingly.
Below you may find a working example:
<h:dataTable value="#{bean.listOfLists}" var="list" binding="#{table}" >
<h:column>
<h:selectOneListbox value="#{bean.selection[table.rowIndex]}" converter="myObjectConverter" >
<f:selectItems value="#{list}" var="obj" itemValue="#{obj}" itemLabel="#{obj.s1}" />
</h:selectOneListbox>
</h:column>
</h:dataTable>
with
MyObject[] selection = new MyObject[listOfLists.size()];

How to display variable number of columns in primefaces datatable

I have the following ArrayList
class Report{
private String manufacturer;
private String color;
private List<Double> revenue;
}
How can I display it on primefaces datatable. I tried using p:columns it is not working.
I have following code on XHTML page
<p:dataTable value="#{tableBean.reportList}" var="report" id="table">
<p:column headerText="Manufacturer">#{report.manufacturer}</p:column>
<p:column headerText="Color">#{report.color}</p:column>
</p:dataTable >
I also tried p:columns and ui:repeat. But I am not able to achieve desired output. result.
<p:columns var="amount" value="#{report.revenue}">#{amount}</p:columns>
<ui:repeat var="amount" value="#{report.revenue}">
<p:column headerText="Revenue">#{amount}</p:column>
</ui:repeat>
I need output as a table with manufacturer name, color and all revenues
Your mistake is that you referenced the currently iterated row (the object behind <p:dataTable var> as <p:columns value>. This is not possible. The amount of columns cannot vary based on the currently iterated row. It can only be set table-wide. The <p:columns value> should reference a property in a backing bean. For a real world example, see also this answer: Creating and populating a DataTable dynamically in JSF2.0.
In your particular case, you just basically want to use <ui:repeat> inside <p:column>:
<p:dataTable value="#{tableBean.reportList}" var="report">
<p:column>
#{report.manufacturer}
</p:column>
<p:column>
#{report.color}
</p:column>
<p:column>
<ui:repeat value="#{report.revenue}" var="revenue">#{revenue}</ui:repeat>
</p:column>
</p:dataTable>
(if you want to print them in separate lines, print a <br/> after #{revenue}; or if you want to print them commaseparated, make use of varStatus)
or maybe a nested table:
<p:column>
<h:dataTable value="#{report.revenue}" var="revenue">#{revenue}</h:dataTable>
</p:column>
Try with
<p:column headerText="Manufacturer">#{report.manufacturer}</p:column>
<p:column headerText="Color">#{report.color}</p:column>
<p:columns value="#{tableBean.columns}" var="column">
<f:facet name="header">
#{column.header}
</f:facet>
#{report.revenue.get(column.property)}
</p:columns>
Where in your bean columns is:
List<ColumnModel> columns;
static public class ColumnModel implements Serializable {
private String header;
private int property;
public ColumnModel(String header, int property) {
this.header = header;
this.property = property;
}
public String getHeader() {
return header;
}
public int getProperty() {
return property;
}
}
Filled as follow:
for(int i = 0; i < TOTAL_NUMBER_OF_REVENUES; i++){
ColumnModel col = new ColumnModel("Revenue "+i, i);
columns.add(col);
}
Source : http://www.primefaces.org/showcase/ui/datatableDynamicColumns.jsf

Editable Datatable using a Dialog in JSF 2.0

I am currently running my web application in JSF 2.0, It also is using Primefaces 2.2RC2.
I know that primefaces gives you the ability to have editable rows, but for my project I would prefer if a user clicks on a commandButton within the table that a dialog is displayed prepopulated with that particular rows values and the user can edit the row that way.
The only way I have gotten this to work is to in the column that contains the commandButton, pass that rows contents as params like the example below:
<p:dataTable var="car" value="#{myBean.cars}" id="carList">
<h:column>
<h:inputText value="#{car.id}" style="width:100%"/>
</h:column>
<h:column>
<h:inputText value="#{car.name}" style="width:100%"/>
</h:column>
<h:column>
<h:commandButton actionListener=#{myBean.updateRow} onsuccess="editCardDialog.show()" >
<f:param name="carId" value=#{car.id} />
<f:param name="carName" value=#{car.name} />
</h:commandButton>
</h:column>
...
</p:dataTable>
So my Question is this, currently the only way I have gotten this to work is to in my backing bean create dummy temp global variables to set the params to so when my dialog opens it can reference the values like this
//myBean.java
private String tempCarId;
private String tempCarName;
public void setTempCarId(String tempCarId) {
this.tempCarId = carId;
}
public String getTempCarId() {
return tempCarId;
}
public void setTempCarName(String tempCarName) {
this.tempCarName = carName;
}
public String getTempCarName() {
return tempCarName;
}
public void updateRow(ActionEvent event) {
String carId = FaceContext...getParameterMap("carId");
String carName = FacesContext...getParameterMap("carName");
setTempCarId(carId);
setTempCarName(carName);
}
Then in the dialog I will just reference those temp variables
<p:dialog>
<h:inputText value=#{myBean.tempCarId} />
<h:inputText value=#{myBean.tempCarName} />
</p:dialog>
I am not sure if this is the correct way of doing it. My gut is telling me its not because it seems extremely redundant to have to create temp variables in my Bean just so I can pass them to the dialog. Does anyone know of a better more concise way of doing this so I dont have to create a million temporary variables in my backing bean?
Just replace the outputTexts in dialog below with inputTexts;
http://www.primefaces.org/showcase/ui/datatableRowSelectionByColumn.jsf
or
http://www.primefaces.org/showcase/ui/datatableRowSelectionInstant.jsf

How to map the value of a h:selectBooleanCheckbox in a h:dataTable within a h:dataTable?

The h:selectBooleanCheckbox in question is in a h:dataTable (of Extras) within a h:dataTable (of Items) within a h:dataTable (of Categories). Many Items are displayed and each Item can have many Extras.
<h:dataTable value="#{bean.categoryList}" var="category">
<h:column>
<h:dataTable value="#{category.itemList}" var="item">
<h:column>
<h:dataTable value="#{item.extraList}" var="extra">
<h:column>
<!-- The h:selectBooleanCheckbox in question //-->
<h:selectBooleanCheckbox value="#{bean.extraSelectedMap[item.id][extra.id]}"/>
</h:column>
<h:commandLink action="#{bean.add}" value="Add">
</h:dataTable>
</h:column>
</h:dataTable>
</h:column>
</h:dataTable>
After the page is rendered I select a check box then select 'Add'. Inside bean.add my
Map<Integer, HashMap<Integer, Boolean>>
has an empty HashMap when I am expecting it to have the id of the extra mapped to the value true.
What is incorrect with the code, or the entire approach, above?
Many thanks and regards.
First, your h:dataTable is three levels deep. If you want to attach the checkbox to a parent managed bean property, then you need to take all levels into account. So,
<h:selectBooleanCheckbox value="#{bean.extraSelectedMap[category.id][item.id][extra.id]}"/>
with a Map<Integer, Map<Integer, Map<Integer, Boolean>>> as property. Otherwise the selections will be overridden for every category until the selected items of the last category ends up in the map.
Second, you need to precreate the map and all nested maps as well. JSF won't do that for you. In other words,
public Bean() {
extraSelectedMap = new HashMap<Integer, Map<Integer, Map<Integer, Boolean>>>();
for (Category category : categoryList) {
Map<Integer, Map<Integer, Boolean>> selectedExtrasPerCategory = new HashMap<Integer, Map<Integer, Boolean>>();
extraSelectedMap.put(category.getId(), selectedExtrasPerCategory);
for (Item item : category.getItemList()) {
Map<Integer, Boolean> selectedExtrasPerItem = new HashMap<Integer, Boolean>();
selectedExtrasPerCategory.put(item.getId(), selectedExtrasPerItem);
}
}
As an alternative, you can also consider to just add a Boolean property to Extra and bind to that instead.

Resources