Displaying the values of a nested array list in JSF data table - jsf

Its been quite some time since i have started developing web pages using JSF but i am still learning most of the stuff. Now I have an interesting question
When I have the values those to be displayed in a data table in the ArrayList and I am adding those ArrayList objects in another array list , so now how will i be able to display them in a data table.
I am doing this since , i need my table to be so dynamic so that i dont know how many columns will i be getting in the result set to be displayed in the page, hece i cannot have a Bean obj for storing my variable values. So i have decided to have something like
ArrayList<ArrayList<String>>
ArrayList<String> - Values for Each row
Does this have a solution that can be provided int he jsf page

Use either plain HTML with a nested <ui:repeat>
<table>
<ui:repeat value="#{bean.rows}" var="row">
<tr>
<ui:repeat value="#{row}" var="column">
<td>#{column}</td>
</ui:repeat>
</tr>
</ui:repeat>
</table>
or grab a 3rd party component library which has sort of a <x:columns> tag like PrimeFaces with <p:columns> and Tomahawk with <t:columns>.
<p:dataTable value="#{bean.rows}" var="row">
<p:columns value="#{row}" var="column">
#{column}
</p:columns>
</p:dataTable>
Either way, you can even keep the columns in a separate list.

Related

How to build a dynamic grid and only show three columns in a row (JSF 2.2 and BootsFaces)

I am trying to layout a page with Bootsfaces and JSF 2.2. I like to show only three column in a row and then start new row but don't know, how to implement this.
<h:form>
<b:container>
<b:row>
<ui:repeat value="#{ClientBean4.custs}" var="custs">
<b:column col-md="4"><h:outputText id="output" value="#{ClientBean4.counter}" /> </b:column>
<h:panelGroup rendered="#{ClientBean4.counter == 0}">
</b:row><b:row>
</h:panelGroup>
</ui:repeat>
</b:row>
</b:container>
</h:form>
after a long time, I wrote above code, but it's givng error like 'h:panelgroup' should be properly closed. It's giving meaning, that I started panelGroup and then closing a row, starting a new row, and then close panelGroup.
So, Is anyone have idea, how to implement a layout, where a row will have three columns (showing customer's object details per column), then close the row and start a new row. obvisouly, I dont know, how many objects will be in the list.
BootFaces offers a component that handles this. More specifically you can use <b:panelGrid columns="3"> to achieve this. This will give you a dynamic grid system that will grow vertically as you populate it but retain the number of rows that you specify.
You can see the component in action here, https://showcase.bootsfaces.net/layout/panelgrids.jsf
PrimeFaces also has a component for this, but I assume you want to use BootFaces as your original code uses it. If you prefer PrimeFaces, you can use the <p:dataGrid> component, which does something similar. This component even handles pagination.

Is it possible to do dynamic column ordering on a p:dataTable without using p:columns?

I'm trying to dynamically display the columns of a p:dataTable: the server dictates which columns are displayed and in which order. It doesn't look like I can set a dynamic order using the regular p:column tag so I'm stuck using the p:columns tag. The problems with the p:columns tag are:
1) The example in the showcase shows it working with String data, where you can map a column name to a field and then use an expression language map to retrieve the data (like a pseudo-getter)
http://www.primefaces.org/showcase/ui/data/datatable/columns.xhtml
If I have different data types though, then I'm probably stuck with a bunch of panels with render attributes based on the type of the data (display Strings one way, display User objects another way, etc).
Example:
<p:dataTable value="#{myBean.rows}" var="row">
<p:columns value="#{myBean.columns}" var="column">
<f:facet name="header">
<h:outputText value="#{column.header}" />
</f:facet>
<!-- The content of the cell is dynamic based on the type of the field -->
<!-- display a String field -->
<h:outputText rendered="#{myBean.isStringType(column.header)}"
value="#{row[column.property]}"/>
<!-- display a Person field -->
<h:outputText rendered="#{myBean.isPersonType(column.header)}"
value="#{row[column.property].name}, #{row[column.property].email}"/>
</p:columns>
</p:dataTable>
2) p:columns only supports a single sortFunction/filterFunction for all columns. Since these columns all have different types of data, they will require many different sorting and filtering methods
A p:column easily allows for the display of different data types as well as the sorting/filtering of the data. The only thing it can't do is have a dynamic order.
Unless I'm missing something? Is there a way to get this to work with p:column ? Or is there an elegant way to have p:columns handle all of this?
It doesn't look like I can set a dynamic order using the regular p:column tag so I'm stuck using the p:columns tag.
If the #{myBean.columns} columns model is constant during at least the view scope, then you'd better use <c:forEach><p:column><c:choose>. It's faster than <p:columns>+rendered, and allows more dynamic freedom as you can declare every <p:column> individually depending on the type instead of having only one <p:columns> whose state changes every iteration round.
<p:dataTable value="#{myBean.rows}" var="row">
<c:forEach items="#{myBean.columns}" var="column">
<c:choose>
<c:when test="#{column.type eq 'STRING'}">
<p:column sortBy="#{row[column.property]}" filterBy="#{row[column.property]}">
#{row[column.property]}
</p:column>
</c:when>
<c:when test="#{column.type eq 'PERSON'}">
<p:column sortBy="#{row[column.property].name}" filterBy="#{row[column.property].name}">
#{row[column.property].name}, #{row[column.property].email}
</p:column>
</c:when>
...
</c:choose>
</c:forEach>
</p:dataTable>
See also:
JSTL in JSF2 Facelets... makes sense?
How to create dynamic JSF form fields

Iterate through List<String> using JSF 2

I have this java code.
List<String> myList = new ArrayList<String>();
myList.add("Hello");
myList.add("World");
I need to loop through the list to display those values in a webpage. I thought of using a dataTable but I don't know how to retrieve each entry on the list.
Ideas? Thanks!
You can use <ui:repeat>:
<ui:repeat value="#{bean.myList}" var="value">
#{value} <br />
</ui:repeat>
If you're not sure if you should use <h:dataTable> or <ui:repeat>, you can check an example that mkyong provides here: JSF 2 repeat tag example
In short: <h:dataTable> renders a <table> HTML component, while <ui:repeat> gives you the flexibility to choose how to display the data.

Any way to list request header names with JSF EL -- without backing bean?

Is there any way to use JSF EL (Java EE 7) to list all the request's header names and corresponding values in a 2-column table, without introducing a backing bean? I can do it if I create a bean and access that from EL, so I do have a means to the end -- but the thing I'm trying to figure out is if it can be done entirely with "out of the box" EL. "That's not possible" would be a fine answer -- I'm still learning.
I thought something like this:
<table>
<ui:repeat value="#{request.getHeaderNames()}" var="hdr">
<tr>
<td>#{hdr}</td>
<td>#{headerValues[hdr]}</td>
</tr>
</ui:repeat>
</table>
But that gives a 1-row table, something like this:
org.apache.catalina.util.Enumerator#2dbf763b [Ljava.lang.String;#74eb32f3
I suspect that because request.getHeaderNames() is giving an enumerator instead of a list of some kind that ui:repeat wants, this approach won't work at all, and I need to do something fundamentally different.
You can just iterate over #{headerValues} itself. You only need either JSTL <c:forEach>,
<dl>
<c:forEach items="#{headerValues}" var="entry">
<dt>#{entry.key}</dt>
<c:forEach items="#{entry.value}" var="headerValue">
<dd>#{headerValue}</dd>
</c:forEach>
</c:forEach>
</dl>
or to make use of EL 2.2 feature to convert Map to Entry[] as follows, as <ui:repeat> doesn't support maps but only lists and arrays:
<dl>
<ui:repeat value="#{headerValues.entrySet().toArray()}" var="entry">
<dt>#{entry.key}</dt>
<ui:repeat value="#{entry.value}" var="headerValue">
<dd>#{headerValue}</dd>
</ui:repeat>
</ui:repeat>
</dl>
Note that each value of #{headerValues} represents a String[], so I've fixed that for you as well, with a proper data structure.

input binding in ui:repeat in jsf

i am using facelets jsf 2.0 with primefaces 3.0.M2 component library.
i am trying to achieve dynamic numbers of rows including iput fields that are filled when a datatable selection occurs.
whenever a selection is made the dynamic rows generated correctly with input fields but after the first selection for following selections dynamic row count changes correctly but the input fields does not update and keeps showing inputs from the first selection.
here is how i iterate list in facelet;
<ui:repeat value="#{goalEntranceBean.selectedCard.parameterList}" var="prmBean" >
<li><h:outputText value="#{prmBean.lookUp.value}"/></li>
<li>
<h:outputText value="Weight:"/>
<p:inputText id="wx" required="true" value="#{prmBean.weight}">
</p:inputText>
<h:outputText value="Percent:"/>
<p:inputText required="true" value="#{prmBean.percent}">
</p:inputText>
</li>
</ui:repeat>
my bean where i get the list of cards and set the selectedCard with rowSelect event in datatable.
#ManagedBean(name = "goalEntranceBean")
#ViewScoped
public class GoalEntranceAction implements Serializable {
private List<ScoreCard> personalCards = new ArrayList<ScoreCard>();
private ScoreCard selectedCard = new ScoreCard();
......
}
when i checked in debug mode i can see the true list but in screen the elements does not change.
This is a common problem (gets asked every couple of days). To make long story short, inputs inside ui:repeat do not work, period.
It is a problem with JSF, a long standing, famous one. Maybe it will be fixed. Maybe not, it seems that no one really cares (I mean - an input? in a... ui:repeat? such crazy scenario!).
A quick-fix is to use a h:dataTable, possibly ungodly abused with css to make it look like a list. A long-fix is to use some iterator from a different library. Primefaces has an element that should work that renders an unordered list.
thanks for your replies. Sorry for forget sharing the solution.
As i mentioned above i have primefaces datatable.
On row selection event i render datatable and want to update the cells of that datatable.
USING p:inputtext easily solved my problem. Now i can change the data on screen and i can see the values after update operation on screen. I don't understand the reason but it works.
<p:dataTable var="orgPrmBean"
value="#{scoreCardOperationsBean.selectedCard.orgParameterList}"
emptyMessage="#{labels.norecord}"
rowKey="#{orgPrmBean.id}"
>
<p:columnGroup type="header">
<p:row>
<p:column headerText="Parameters" colspan="3" style="text-align:left;width:480;"/>
</p:row>
</p:columnGroup>
<p:column style="text-align:left;width:200px;">
<h:outputText value="#{orgPrmBean.info}"/>
</p:column>
<p:column style="text-align:left;width:180px;">
<p:inputText value="#{orgPrmBean.weight}"
rendered="#{scoreCardOperationsBean.selectedCard.goalEdit}">
<f:convertNumber maxFractionDigits="0"/>
</p:inputText>
</p:column>
</p:dataTable>
It IS possible to make it work, but the solution is to bind the inputs to a backing bean, and update the values of the controls in the backing bean via listeners (using the new value received in the argument). Obviously this isn't a good solution if you have a complex form, as you need to add a listener/control in the backing bean for each control in the page, but it's practical if you just have one or two inputs.

Resources