Netbeans doesn't autocomplete properties of var of nested <ui:repeat> - jsf

Let me say I have a Book Library with a list of Book. A Book has a List of Page. Page has a list of Line.
In JSF, i'm trying to display all the lines, now I'm using <h:dataTable> or <ui:repeat> to iterate through the lists. When I'm on second level of hierarchy which is page, instead of showing the properties of page as lines, netbeans only show the properties of book again as available properties
<ui:repeat value="#{bookLibrary.books}" var="book">
<ui:repeat value="#{book.pages}" var="page">
<ui:repeat value="#{page.???}" var="line">
</ui:repeat>
</ui:repeat> </ui:repeat>

Yes, I now found out that it works if I add the field manually. Its the code completion that's leading me to believe my code is wrong

Related

Dynamic id for primefaces datatable [duplicate]

I'm trying to assign an id to a component inside a <ui:repeat> like that:
<ui:repeat value="#{bean.columns}" var="column">
<h:panelGroup layout="block" id="column_#{column.id}"
styleClass="#{column.id} dashboard_column">
The thing is that #{column.id} value is being placed properly inside the styleClass value but its not being set inside the id attribute. All that is being set inside the id attribute is the automatically generated id by the JSF + my hard coded value column_.
If I remove the hard coded column_ I get an exception:
java.lang.IllegalArgumentException: component identifier must not be a zero-length String
at
Any Ideas?
This is not possible with a render-time tag such as <ui:repeat>. The <ui:repeat> will however by itself already ensure the uniqueness of the generated client ID by prepending it with the row index. So just remove the EL part from the ID attribute of the component.
<ui:repeat value="#{bean.columns}" var="column">
<h:panelGroup layout="block" id="column">
With a view build time tag such as <c:forEach> (which will basically generate multiple <h:panelGroup> components instead of only one which is rendered multiple times), it is possible to specify a dynamic ID like that.
<c:forEach items="#{bean.columns}" var="column">
<h:panelGroup layout="block" id="column_#{column.id}">
(you should only be well aware of how JSTL works in Facelets)
An alternative is to use a static <div> element instead of a JSF <h:panelGroup layout="block"> component.
<ui:repeat value="#{bean.columns}" var="column">
<div id="column_#{column.id}">
See also:
JSTL in JSF2 Facelets... makes sense?
JSF prefixes the id automatically. If you simply write id="column" the generated HTML will contain such identifiers:
myForm:0:column
myForm:1:column
myForm:2:column
and so on.
Anyway: Do never use JSTL tags (like c:foreach and c:if) in JSF templates. They cause random behaviour, very difficult to debug. And if they work, the slow down the application a lot.
Use ui:repeat for loops, and ui:fragment for conditional blocks. Note that there is no replacement for c:set, such a construct does not exist anymore in JSF 2.

c:forEach or ui:repeat inside h:dataTable [duplicate]

I have to dinamically produce a list of tables. Each of these have a variable number of columns (with fixed rows).
To perform this I first put a <p:panelGrid> inside an <ui:repeat>: so I correctly produced a list of tables.
Then, to dinamically produce the columns, I tried put both an <ui:repeat> or a <c:forEach> inside the <p:panelGrid>. In the result I obtain no rows.
I written a minimal example here. In the bean testBackingBean, I have defined (and initialized) the variable ArrayList<ArrayList<String>> tables. This is the xhtml that does not produce the expected results:
<ui:repeat var="table" value="#{testBackingBean.tables}">
<p:panelGrid>
<f:facet name="header">
<p:row>
<p:column >header of #{table}</p:column>
</p:row>
</f:facet>
<p:row>
<c:forEach var="row" items="${table}">
<p:column>#{row}</p:column>
</c:forEach>
</p:row>
</p:panelGrid>
</ui:repeat>
Noteworthy the header-row correctly converts #{table} into string. The problem is that I see no rows of data.
Also, if I use the <table> instead of the <p:panelGrid> everything work as excpected.
Also, I tried different permutations of <c:forEach> and <ui:repeat> with no succes.
So, how can I dinamically produce more tables (using prime-faces) and set a dinamical number of columns?
Thanks!
EDIT: I would like to use two <c:forEach>, but even with one only <c:forEach> I get an empty result. In fact if I try the following xhtml:
<c:forEach items="${testBackingBean.tables}" var="tabella">
current element: #{tabella}
</c:forEach>
then I get an empty result. (I know,this is a different question)
The transition from the XHTML source code to the generated HTML output is a two-step process.
First, during view build time, the XHTML source code is parsed and turned in a tree of Java UIComponent instances representing the JSF UI component tree, as available by FacesContext#getViewRoot().
Then, during view render time, the JSF UI component tree produces HTML output and writes it to the HTTP resopnse, starting with UIViewRoot#encodeAll() method.
Taghandlers like all JSTL <c:xxx> tags, several JSF <f:xxx> tags and only a few Facelets <ui:xxx> tags run during view build time. UI components like all JSF <h:xxx> tags, several Facelets <ui:xxx> tags and only a few JSF <f:xxx> tags run during view render time.
The <c:forEach> is a taghandler and the <ui:repeat> is an UI component.
In other words, the UI components which are declared inside <c:forEach> are recreated multiple times in the JSF component tree based on <c:forEach items> during view build time which in turn individually produce each their own HTML output during view render time. The UI components which are declared inside <ui:repeat> are created only once in the JSF component tree during view build time which in turn are reused multiple times based on <ui:repeat value> to produce HTML output during view render time.
Your concrete problem is caused by the fact that <ui:repeat var="table"> is only available during view render time, not during view build time. The <c:forEach> is basically retrieving a #{null} as value when it's about to run during view build time.
You can solve this by replacing the outer <ui:repeat> by <c:forEach>. Although I wonder if you couldn't better use <ui:repeat><p:dataTable><p:columns> instead.
See also:
JSTL in JSF2 Facelets... makes sense?

Iterating List of Lists in JSF view

I'm trying to iterate a List> on my JSF view using ui:repeat tags. It looks like this:
<h:form>
<ui:repeat value="#{myController.currentEntry.pages}" var="page" varStatus="pageStatus">
<p:fieldset rendered="#{myController.currentEntryPage == pageStatus.index}">
<ui:repeat value="#{page}" var="item" varStatus="itemStatus">
<h:outputText value="#{itemStatus.index + 1}. #{item.anotherClass.text}" />
</ui:repeat>
<p:fieldset>
</ui:repeat>
</h:form>
My class Item, located in models package, contains a reference to an object of AnotherClass, also in models package. I have checked in debugger and, just before the redirect to my view is returned, myController.currentEntry.pages is well formed.
I get the following error, however:
javax.servlet.ServletException: /my_view.xhtml #10,109 value="#{itemStatus.index + 1}. #{item.anotherClass.text}": Property 'anotherClass' not readable on type models.AnotherClass
javax.faces.webapp.FacesServlet.service(FacesServlet.java:422)
org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
filters.Auth.doFilter(Auth.java:19)
filters.Encoding.doFilter(Encoding.java:28)
What is this all about? How is JSF managing to map item to item.anotherClass? I know ui:repeat is full of bugs, but none of what I found points to this kind of problem.
Is there any other way to achieve what I'm trying to do? My project uses Primefaces. It is close to the end and even closer to delivery deadline, so switching to another library is not an option.
EDIT:
I've switched to a more elegant solution that doesn't require me to iterate the whole matrix:
<ui:repeat value="#{myController.currentEntryPageItems}" var="item" varStatus="itemStatus">
getCurrentEntryPageItems() being a method that returns myController.currentEntry.pages.get(myController.currentEntryPage).
I would still like to know if 2d iteration can be done with ui:repeat so I'll leave the question open.

Generating a list of links to be displayed in Facelets

I need to have a list of links generated by JSF and displayed in Facelets. The bean would contain all of the links and where they need to point to, and then I assume some method would run to disperse all of them which could be called by some JSF attribute in the Facelets page.
I'm kind of clueless. How can I achieve this?
You can use ui:repeat tag:
<ui:repeat value="#{bean.links}" var="link" varStatus="status">
<h:outputLink value="#{link.url}">
<h:outputLabel value="#{link.name}"/>
</h:outputLink>
<h:outputText value=", " rendered="#{not status.last}"/>
</ui:repeat>
bean is managed bean that have getLinks method. getLinks method returns list of links. Every link is an object with name and url properties. All links are separated by commas.

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

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.

Resources