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

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?

Related

how to update ui:repeat and still component id [duplicate]

I would like to output a bit of Facelets code conditionally.
For that purpose, the JSTL tags seem to work fine:
<c:if test="${lpc.verbose}">
...
</c:if>
However, I'm not sure if this is a best practice? Is there another way to achieve my goal?
Introduction
JSTL <c:xxx> tags are all taghandlers and they are executed during view build time, while JSF <h:xxx> tags are all UI components and they are executed during view render time.
Note that from JSF's own <f:xxx> and <ui:xxx> tags only those which do not extend from UIComponent are also taghandlers, e.g. <f:validator>, <ui:include>, <ui:define>, etc. The ones which extend from UIComponent are also JSF UI components, e.g. <f:param>, <ui:fragment>, <ui:repeat>, etc. From JSF UI components only the id and binding attributes are also evaluated during view build time. Thus the below answer as to JSTL lifecycle also applies to the id and binding attributes of JSF components.
The view build time is that moment when the XHTML/JSP file is to be parsed and converted to a JSF component tree which is then stored as UIViewRoot of the FacesContext. The view render time is that moment when the JSF component tree is about to generate HTML, starting with UIViewRoot#encodeAll(). So: JSF UI components and JSTL tags doesn't run in sync as you'd expect from the coding. You can visualize it as follows: JSTL runs from top to bottom first, producing the JSF component tree, then it's JSF's turn to run from top to bottom again, producing the HTML output.
<c:forEach> vs <ui:repeat>
For example, this Facelets markup iterating over 3 items using <c:forEach>:
<c:forEach items="#{bean.items}" var="item">
<h:outputText id="item_#{item.id}" value="#{item.value}" />
</c:forEach>
...creates during view build time three separate <h:outputText> components in the JSF component tree, roughly represented like this:
<h:outputText id="item_1" value="#{bean.items[0].value}" />
<h:outputText id="item_2" value="#{bean.items[1].value}" />
<h:outputText id="item_3" value="#{bean.items[2].value}" />
...which in turn individually generate their HTML output during view render time:
<span id="item_1">value1</span>
<span id="item_2">value2</span>
<span id="item_3">value3</span>
Note that you need to manually ensure the uniqueness of the component IDs and that those are also evaluated during view build time.
While this Facelets markup iterating over 3 items using <ui:repeat>, which is a JSF UI component:
<ui:repeat id="items" value="#{bean.items}" var="item">
<h:outputText id="item" value="#{item.value}" />
</ui:repeat>
...already ends up as-is in the JSF component tree whereby the very same <h:outputText> component is during view render time being reused to generate HTML output based on current iteration round:
<span id="items:0:item">value1</span>
<span id="items:1:item">value2</span>
<span id="items:2:item">value3</span>
Note that the <ui:repeat> as being a NamingContainer component already ensured the uniqueness of the client ID based on iteration index; it's also not possible to use EL in id attribute of child components this way as it is also evaluated during view build time while #{item} is only available during view render time. Same is true for an h:dataTable and similar components.
<c:if>/<c:choose> vs rendered
As another example, this Facelets markup conditionally adding different tags using <c:if> (you can also use <c:choose><c:when><c:otherwise> for this):
<c:if test="#{field.type eq 'TEXT'}">
<h:inputText ... />
</c:if>
<c:if test="#{field.type eq 'PASSWORD'}">
<h:inputSecret ... />
</c:if>
<c:if test="#{field.type eq 'SELECTONE'}">
<h:selectOneMenu ... />
</c:if>
...will in case of type = TEXT only add the <h:inputText> component to the JSF component tree:
<h:inputText ... />
While this Facelets markup:
<h:inputText ... rendered="#{field.type eq 'TEXT'}" />
<h:inputSecret ... rendered="#{field.type eq 'PASSWORD'}" />
<h:selectOneMenu ... rendered="#{field.type eq 'SELECTONE'}" />
...will end up exactly as above in the JSF component tree regardless of the condition. This may thus end up in a "bloated" component tree when you have many of them and they are actually based on a "static" model (i.e. the field does not ever change during at least the view scope). Also, you may run into EL trouble when you deal with subclasses with additional properties in Mojarra versions before 2.2.7.
<c:set> vs <ui:param>
They are not interchangeable. The <c:set> sets a variable in the EL scope, which is accessible only after the tag location during view build time, but anywhere in the view during view render time. The <ui:param> passes an EL variable to a Facelet template included via <ui:include>, <ui:decorate template>, or <ui:composition template>. Older JSF versions had bugs whereby the <ui:param> variable is also available outside the Facelet template in question, this should never be relied upon.
The <c:set> without a scope attribute will behave like an alias. It does not cache the result of the EL expression in any scope. It can thus perfectly fine be used inside for example iterating JSF components. Thus, e.g. below will work fine:
<ui:repeat value="#{bean.products}" var="product">
<c:set var="price" value="#{product.price}" />
<h:outputText value="#{price}" />
</ui:repeat>
It's only not suitable for e.g. calculating the sum in a loop. For that instead use EL 3.0 stream:
<ui:repeat value="#{bean.products}" var="product">
...
</ui:repeat>
<p>Total price: #{bean.products.stream().map(product->product.price).sum()}</p>
Only, when you set the scope attribute with one of allowable values request, view, session, or application, then it will be evaluated immediately during view build time and stored in the specified scope.
<c:set var="dev" value="#{facesContext.application.projectStage eq 'Development'}" scope="application" />
This will be evaluated only once and available as #{dev} throughout the entire application.
Use JSTL to control JSF component tree building
Using JSTL may only lead to unexpected results when being used inside JSF iterating components such as <h:dataTable>, <ui:repeat>, etc, or when JSTL tag attributes depend on results of JSF events such as preRenderView or submitted form values in the model which aren't available during view build time. So, use JSTL tags only to control flow of JSF component tree building. Use JSF UI components to control flow of HTML output generation. Do not bind the var of iterating JSF components to JSTL tag attributes. Do not rely on JSF events in JSTL tag attributes.
Anytime you think you need to bind a component to the backing bean via binding, or grab one via findComponent(), and create/manipulate its children using Java code in a backing bean with new SomeComponent() and what not, then you should immediately stop and consider using JSTL instead. As JSTL is also XML based, the code needed to dynamically create JSF components will become so much better readable and maintainable.
Important to know is that Mojarra versions older than 2.1.18 had a bug in partial state saving when referencing a view scoped bean in a JSTL tag attribute. The whole view scoped bean would be newly recreated instead of retrieved from the view tree (simply because the complete view tree isn't available yet at the point JSTL runs). If you're expecting or storing some state in the view scoped bean by a JSTL tag attribute, then it won't return the value you expect, or it will be "lost" in the real view scoped bean which is restored after the view tree is built. In case you can't upgrade to Mojarra 2.1.18 or newer, the work around is to turn off partial state saving in web.xml like below:
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
See also:
What's the view build time?
How does the 'binding' attribute work in JSF? When and how should it be used?
How to refactor snippet of old JSP to some JSF equivalent?
Should PARTIAL_STATE_SAVING be set to false?
Communication in JSF 2.0 - #ViewScoped fails in tag handlers
To see some real world examples where JSTL tags are helpful (i.e. when really properly used during building the view), see the following questions/answers:
How to make a grid of JSF composite component?
Create table columns dynamically in JSF
How to custom layout h:selectOneRadio
Conditional variable definition in JSF
How to make composite component similar to <h:selectOneRadio />
JSF 2 -- Composite component with optional listener attribute on f:ajax
Nested JSF Composite Components leading to a Stack Overflow exception
In a nutshell
As to your concrete functional requirement, if you want to render JSF components conditionally, use the rendered attribute on the JSF HTML component instead, particularly if #{lpc} represents the currently iterated item of a JSF iterating component such as <h:dataTable> or <ui:repeat>.
<h:someComponent rendered="#{lpc.verbose}">
...
</h:someComponent>
Or, if you want to build (create/add) JSF components conditionally, then keep using JSTL. It's way much better than verbosely doing new SomeComponent() in java.
<c:if test="#{lpc.verbose}">
<h:someComponent>
...
</h:someComponent>
</c:if>
See also:
Conditionally displaying JSF components
JSTL c:if doesn't work inside a JSF h:dataTable
Specify conditional rendering of element inside <ui:repeat>? The <c:if> does not seem to work
use
<h:panelGroup rendered="#{lpc.verbose}">
...
</h:panelGroup>
For switch-like output, you can use the switch face from PrimeFaces Extensions.

Render and build time in JSF [duplicate]

I would like to output a bit of Facelets code conditionally.
For that purpose, the JSTL tags seem to work fine:
<c:if test="${lpc.verbose}">
...
</c:if>
However, I'm not sure if this is a best practice? Is there another way to achieve my goal?
Introduction
JSTL <c:xxx> tags are all taghandlers and they are executed during view build time, while JSF <h:xxx> tags are all UI components and they are executed during view render time.
Note that from JSF's own <f:xxx> and <ui:xxx> tags only those which do not extend from UIComponent are also taghandlers, e.g. <f:validator>, <ui:include>, <ui:define>, etc. The ones which extend from UIComponent are also JSF UI components, e.g. <f:param>, <ui:fragment>, <ui:repeat>, etc. From JSF UI components only the id and binding attributes are also evaluated during view build time. Thus the below answer as to JSTL lifecycle also applies to the id and binding attributes of JSF components.
The view build time is that moment when the XHTML/JSP file is to be parsed and converted to a JSF component tree which is then stored as UIViewRoot of the FacesContext. The view render time is that moment when the JSF component tree is about to generate HTML, starting with UIViewRoot#encodeAll(). So: JSF UI components and JSTL tags doesn't run in sync as you'd expect from the coding. You can visualize it as follows: JSTL runs from top to bottom first, producing the JSF component tree, then it's JSF's turn to run from top to bottom again, producing the HTML output.
<c:forEach> vs <ui:repeat>
For example, this Facelets markup iterating over 3 items using <c:forEach>:
<c:forEach items="#{bean.items}" var="item">
<h:outputText id="item_#{item.id}" value="#{item.value}" />
</c:forEach>
...creates during view build time three separate <h:outputText> components in the JSF component tree, roughly represented like this:
<h:outputText id="item_1" value="#{bean.items[0].value}" />
<h:outputText id="item_2" value="#{bean.items[1].value}" />
<h:outputText id="item_3" value="#{bean.items[2].value}" />
...which in turn individually generate their HTML output during view render time:
<span id="item_1">value1</span>
<span id="item_2">value2</span>
<span id="item_3">value3</span>
Note that you need to manually ensure the uniqueness of the component IDs and that those are also evaluated during view build time.
While this Facelets markup iterating over 3 items using <ui:repeat>, which is a JSF UI component:
<ui:repeat id="items" value="#{bean.items}" var="item">
<h:outputText id="item" value="#{item.value}" />
</ui:repeat>
...already ends up as-is in the JSF component tree whereby the very same <h:outputText> component is during view render time being reused to generate HTML output based on current iteration round:
<span id="items:0:item">value1</span>
<span id="items:1:item">value2</span>
<span id="items:2:item">value3</span>
Note that the <ui:repeat> as being a NamingContainer component already ensured the uniqueness of the client ID based on iteration index; it's also not possible to use EL in id attribute of child components this way as it is also evaluated during view build time while #{item} is only available during view render time. Same is true for an h:dataTable and similar components.
<c:if>/<c:choose> vs rendered
As another example, this Facelets markup conditionally adding different tags using <c:if> (you can also use <c:choose><c:when><c:otherwise> for this):
<c:if test="#{field.type eq 'TEXT'}">
<h:inputText ... />
</c:if>
<c:if test="#{field.type eq 'PASSWORD'}">
<h:inputSecret ... />
</c:if>
<c:if test="#{field.type eq 'SELECTONE'}">
<h:selectOneMenu ... />
</c:if>
...will in case of type = TEXT only add the <h:inputText> component to the JSF component tree:
<h:inputText ... />
While this Facelets markup:
<h:inputText ... rendered="#{field.type eq 'TEXT'}" />
<h:inputSecret ... rendered="#{field.type eq 'PASSWORD'}" />
<h:selectOneMenu ... rendered="#{field.type eq 'SELECTONE'}" />
...will end up exactly as above in the JSF component tree regardless of the condition. This may thus end up in a "bloated" component tree when you have many of them and they are actually based on a "static" model (i.e. the field does not ever change during at least the view scope). Also, you may run into EL trouble when you deal with subclasses with additional properties in Mojarra versions before 2.2.7.
<c:set> vs <ui:param>
They are not interchangeable. The <c:set> sets a variable in the EL scope, which is accessible only after the tag location during view build time, but anywhere in the view during view render time. The <ui:param> passes an EL variable to a Facelet template included via <ui:include>, <ui:decorate template>, or <ui:composition template>. Older JSF versions had bugs whereby the <ui:param> variable is also available outside the Facelet template in question, this should never be relied upon.
The <c:set> without a scope attribute will behave like an alias. It does not cache the result of the EL expression in any scope. It can thus perfectly fine be used inside for example iterating JSF components. Thus, e.g. below will work fine:
<ui:repeat value="#{bean.products}" var="product">
<c:set var="price" value="#{product.price}" />
<h:outputText value="#{price}" />
</ui:repeat>
It's only not suitable for e.g. calculating the sum in a loop. For that instead use EL 3.0 stream:
<ui:repeat value="#{bean.products}" var="product">
...
</ui:repeat>
<p>Total price: #{bean.products.stream().map(product->product.price).sum()}</p>
Only, when you set the scope attribute with one of allowable values request, view, session, or application, then it will be evaluated immediately during view build time and stored in the specified scope.
<c:set var="dev" value="#{facesContext.application.projectStage eq 'Development'}" scope="application" />
This will be evaluated only once and available as #{dev} throughout the entire application.
Use JSTL to control JSF component tree building
Using JSTL may only lead to unexpected results when being used inside JSF iterating components such as <h:dataTable>, <ui:repeat>, etc, or when JSTL tag attributes depend on results of JSF events such as preRenderView or submitted form values in the model which aren't available during view build time. So, use JSTL tags only to control flow of JSF component tree building. Use JSF UI components to control flow of HTML output generation. Do not bind the var of iterating JSF components to JSTL tag attributes. Do not rely on JSF events in JSTL tag attributes.
Anytime you think you need to bind a component to the backing bean via binding, or grab one via findComponent(), and create/manipulate its children using Java code in a backing bean with new SomeComponent() and what not, then you should immediately stop and consider using JSTL instead. As JSTL is also XML based, the code needed to dynamically create JSF components will become so much better readable and maintainable.
Important to know is that Mojarra versions older than 2.1.18 had a bug in partial state saving when referencing a view scoped bean in a JSTL tag attribute. The whole view scoped bean would be newly recreated instead of retrieved from the view tree (simply because the complete view tree isn't available yet at the point JSTL runs). If you're expecting or storing some state in the view scoped bean by a JSTL tag attribute, then it won't return the value you expect, or it will be "lost" in the real view scoped bean which is restored after the view tree is built. In case you can't upgrade to Mojarra 2.1.18 or newer, the work around is to turn off partial state saving in web.xml like below:
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
See also:
What's the view build time?
How does the 'binding' attribute work in JSF? When and how should it be used?
How to refactor snippet of old JSP to some JSF equivalent?
Should PARTIAL_STATE_SAVING be set to false?
Communication in JSF 2.0 - #ViewScoped fails in tag handlers
To see some real world examples where JSTL tags are helpful (i.e. when really properly used during building the view), see the following questions/answers:
How to make a grid of JSF composite component?
Create table columns dynamically in JSF
How to custom layout h:selectOneRadio
Conditional variable definition in JSF
How to make composite component similar to <h:selectOneRadio />
JSF 2 -- Composite component with optional listener attribute on f:ajax
Nested JSF Composite Components leading to a Stack Overflow exception
In a nutshell
As to your concrete functional requirement, if you want to render JSF components conditionally, use the rendered attribute on the JSF HTML component instead, particularly if #{lpc} represents the currently iterated item of a JSF iterating component such as <h:dataTable> or <ui:repeat>.
<h:someComponent rendered="#{lpc.verbose}">
...
</h:someComponent>
Or, if you want to build (create/add) JSF components conditionally, then keep using JSTL. It's way much better than verbosely doing new SomeComponent() in java.
<c:if test="#{lpc.verbose}">
<h:someComponent>
...
</h:someComponent>
</c:if>
See also:
Conditionally displaying JSF components
JSTL c:if doesn't work inside a JSF h:dataTable
Specify conditional rendering of element inside <ui:repeat>? The <c:if> does not seem to work
use
<h:panelGroup rendered="#{lpc.verbose}">
...
</h:panelGroup>
For switch-like output, you can use the switch face from PrimeFaces Extensions.

JSF Dynamic PanelGrid Empty [duplicate]

I would like to output a bit of Facelets code conditionally.
For that purpose, the JSTL tags seem to work fine:
<c:if test="${lpc.verbose}">
...
</c:if>
However, I'm not sure if this is a best practice? Is there another way to achieve my goal?
Introduction
JSTL <c:xxx> tags are all taghandlers and they are executed during view build time, while JSF <h:xxx> tags are all UI components and they are executed during view render time.
Note that from JSF's own <f:xxx> and <ui:xxx> tags only those which do not extend from UIComponent are also taghandlers, e.g. <f:validator>, <ui:include>, <ui:define>, etc. The ones which extend from UIComponent are also JSF UI components, e.g. <f:param>, <ui:fragment>, <ui:repeat>, etc. From JSF UI components only the id and binding attributes are also evaluated during view build time. Thus the below answer as to JSTL lifecycle also applies to the id and binding attributes of JSF components.
The view build time is that moment when the XHTML/JSP file is to be parsed and converted to a JSF component tree which is then stored as UIViewRoot of the FacesContext. The view render time is that moment when the JSF component tree is about to generate HTML, starting with UIViewRoot#encodeAll(). So: JSF UI components and JSTL tags doesn't run in sync as you'd expect from the coding. You can visualize it as follows: JSTL runs from top to bottom first, producing the JSF component tree, then it's JSF's turn to run from top to bottom again, producing the HTML output.
<c:forEach> vs <ui:repeat>
For example, this Facelets markup iterating over 3 items using <c:forEach>:
<c:forEach items="#{bean.items}" var="item">
<h:outputText id="item_#{item.id}" value="#{item.value}" />
</c:forEach>
...creates during view build time three separate <h:outputText> components in the JSF component tree, roughly represented like this:
<h:outputText id="item_1" value="#{bean.items[0].value}" />
<h:outputText id="item_2" value="#{bean.items[1].value}" />
<h:outputText id="item_3" value="#{bean.items[2].value}" />
...which in turn individually generate their HTML output during view render time:
<span id="item_1">value1</span>
<span id="item_2">value2</span>
<span id="item_3">value3</span>
Note that you need to manually ensure the uniqueness of the component IDs and that those are also evaluated during view build time.
While this Facelets markup iterating over 3 items using <ui:repeat>, which is a JSF UI component:
<ui:repeat id="items" value="#{bean.items}" var="item">
<h:outputText id="item" value="#{item.value}" />
</ui:repeat>
...already ends up as-is in the JSF component tree whereby the very same <h:outputText> component is during view render time being reused to generate HTML output based on current iteration round:
<span id="items:0:item">value1</span>
<span id="items:1:item">value2</span>
<span id="items:2:item">value3</span>
Note that the <ui:repeat> as being a NamingContainer component already ensured the uniqueness of the client ID based on iteration index; it's also not possible to use EL in id attribute of child components this way as it is also evaluated during view build time while #{item} is only available during view render time. Same is true for an h:dataTable and similar components.
<c:if>/<c:choose> vs rendered
As another example, this Facelets markup conditionally adding different tags using <c:if> (you can also use <c:choose><c:when><c:otherwise> for this):
<c:if test="#{field.type eq 'TEXT'}">
<h:inputText ... />
</c:if>
<c:if test="#{field.type eq 'PASSWORD'}">
<h:inputSecret ... />
</c:if>
<c:if test="#{field.type eq 'SELECTONE'}">
<h:selectOneMenu ... />
</c:if>
...will in case of type = TEXT only add the <h:inputText> component to the JSF component tree:
<h:inputText ... />
While this Facelets markup:
<h:inputText ... rendered="#{field.type eq 'TEXT'}" />
<h:inputSecret ... rendered="#{field.type eq 'PASSWORD'}" />
<h:selectOneMenu ... rendered="#{field.type eq 'SELECTONE'}" />
...will end up exactly as above in the JSF component tree regardless of the condition. This may thus end up in a "bloated" component tree when you have many of them and they are actually based on a "static" model (i.e. the field does not ever change during at least the view scope). Also, you may run into EL trouble when you deal with subclasses with additional properties in Mojarra versions before 2.2.7.
<c:set> vs <ui:param>
They are not interchangeable. The <c:set> sets a variable in the EL scope, which is accessible only after the tag location during view build time, but anywhere in the view during view render time. The <ui:param> passes an EL variable to a Facelet template included via <ui:include>, <ui:decorate template>, or <ui:composition template>. Older JSF versions had bugs whereby the <ui:param> variable is also available outside the Facelet template in question, this should never be relied upon.
The <c:set> without a scope attribute will behave like an alias. It does not cache the result of the EL expression in any scope. It can thus perfectly fine be used inside for example iterating JSF components. Thus, e.g. below will work fine:
<ui:repeat value="#{bean.products}" var="product">
<c:set var="price" value="#{product.price}" />
<h:outputText value="#{price}" />
</ui:repeat>
It's only not suitable for e.g. calculating the sum in a loop. For that instead use EL 3.0 stream:
<ui:repeat value="#{bean.products}" var="product">
...
</ui:repeat>
<p>Total price: #{bean.products.stream().map(product->product.price).sum()}</p>
Only, when you set the scope attribute with one of allowable values request, view, session, or application, then it will be evaluated immediately during view build time and stored in the specified scope.
<c:set var="dev" value="#{facesContext.application.projectStage eq 'Development'}" scope="application" />
This will be evaluated only once and available as #{dev} throughout the entire application.
Use JSTL to control JSF component tree building
Using JSTL may only lead to unexpected results when being used inside JSF iterating components such as <h:dataTable>, <ui:repeat>, etc, or when JSTL tag attributes depend on results of JSF events such as preRenderView or submitted form values in the model which aren't available during view build time. So, use JSTL tags only to control flow of JSF component tree building. Use JSF UI components to control flow of HTML output generation. Do not bind the var of iterating JSF components to JSTL tag attributes. Do not rely on JSF events in JSTL tag attributes.
Anytime you think you need to bind a component to the backing bean via binding, or grab one via findComponent(), and create/manipulate its children using Java code in a backing bean with new SomeComponent() and what not, then you should immediately stop and consider using JSTL instead. As JSTL is also XML based, the code needed to dynamically create JSF components will become so much better readable and maintainable.
Important to know is that Mojarra versions older than 2.1.18 had a bug in partial state saving when referencing a view scoped bean in a JSTL tag attribute. The whole view scoped bean would be newly recreated instead of retrieved from the view tree (simply because the complete view tree isn't available yet at the point JSTL runs). If you're expecting or storing some state in the view scoped bean by a JSTL tag attribute, then it won't return the value you expect, or it will be "lost" in the real view scoped bean which is restored after the view tree is built. In case you can't upgrade to Mojarra 2.1.18 or newer, the work around is to turn off partial state saving in web.xml like below:
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
See also:
What's the view build time?
How does the 'binding' attribute work in JSF? When and how should it be used?
How to refactor snippet of old JSP to some JSF equivalent?
Should PARTIAL_STATE_SAVING be set to false?
Communication in JSF 2.0 - #ViewScoped fails in tag handlers
To see some real world examples where JSTL tags are helpful (i.e. when really properly used during building the view), see the following questions/answers:
How to make a grid of JSF composite component?
Create table columns dynamically in JSF
How to custom layout h:selectOneRadio
Conditional variable definition in JSF
How to make composite component similar to <h:selectOneRadio />
JSF 2 -- Composite component with optional listener attribute on f:ajax
Nested JSF Composite Components leading to a Stack Overflow exception
In a nutshell
As to your concrete functional requirement, if you want to render JSF components conditionally, use the rendered attribute on the JSF HTML component instead, particularly if #{lpc} represents the currently iterated item of a JSF iterating component such as <h:dataTable> or <ui:repeat>.
<h:someComponent rendered="#{lpc.verbose}">
...
</h:someComponent>
Or, if you want to build (create/add) JSF components conditionally, then keep using JSTL. It's way much better than verbosely doing new SomeComponent() in java.
<c:if test="#{lpc.verbose}">
<h:someComponent>
...
</h:someComponent>
</c:if>
See also:
Conditionally displaying JSF components
JSTL c:if doesn't work inside a JSF h:dataTable
Specify conditional rendering of element inside <ui:repeat>? The <c:if> does not seem to work
use
<h:panelGroup rendered="#{lpc.verbose}">
...
</h:panelGroup>
For switch-like output, you can use the switch face from PrimeFaces Extensions.

Why can <c:forEach> or <ui:repeat> not access <p:dataTable var>?

I am working with jsf Mojarra 2.2.7, Java 8, Primefaces 5.1 and netbeans 8.0.2
I have a class Event with a property List<GameRecord> gameRecordList. GameRecord includes List<Boolean> gamesEntered and other properties. The idea is I have a list of people in an event and am configuring if they are entered into bets or competitions.
In my .xhtml file I have
<p:dataTable value="#{events.gameRecordList}" var="item" rowIndexVar="rowIndex">
<p:column>#{item.field1}</p:column>
<p:column>#{item.field2}</p:column>
<c:forEach items="#{events.gameRecordList.get(rowIndex).gamesEntered}" var="game">
<p:column>
<p:selectBooleanCheckbox value="#{game}"/>
</p:column>
</c:forEach>
</p:dataTable>
The <c:forEach> should work with value="#{item.gamesEntered}" rather than the full string but it does not. I have tried <ui:repeat> but either way the page comes up blank where this data should have appeared.
Does this make sense or is there a reason the full addressing is required to make it work?
The <c:forEach> should work with value="#{item.gamesEntered}" rather than the full string but it does not.
JSTL tags run during view build time, building JSF component tree. JSF components run during view render time, producing HTML output. So at the moment <c:forEach> runs, <p:dataTable> hasn't run and its var is nowhere available and will evaluate as null. Note that the same applies to rowIndexVar, which will evaluate as 0 (the default value of an int).
See also
JSTL in JSF2 Facelets... makes sense?
I have tried <ui:repeat> but either way the page comes up blank where this data should have appeared.
UIData components can only accept UIColumn children. The <ui:repeat> isn't such one. The <c:forEach> works because it basically produces a bunch of physical <p:column> components for the datatable. You're lucky that each item has apparently the same amount of gamesEntered as the first item, this would otherwise have failed hard as well.
See also:
How to use ui:repeat in datatable to append columns?
By the way, you need <p:columns> which is basically an <ui:repeat> which extends from UIColumn class. But also here, its value cannot be set on a per-row basis, only on a per-table basis. The rowIndexVar isn't available in <p:columns value> and would evaluate as 0 anyway.
<p:dataTable value="#{events.gameRecordList}" var="item" rowIndexVar="rowIndex">
<p:column>#{item.field1}</p:column>
<p:column>#{item.field2}</p:column>
<p:columns value="#{events.gameRecordList[0].gamesEntered}" columnIndexVar="columnIndex">
<p:selectBooleanCheckbox value="#{events.gameRecordList[rowIndex].gamesEntered[columnIndex]}"/>
</p:columns>
</p:dataTable>
See also:
Primefaces static and dynamic columns in datatable
Dynamic columns with List<List> in <p:dataTable><p:columns>

Are JSTL tags evaluated before [duplicate]

I would like to output a bit of Facelets code conditionally.
For that purpose, the JSTL tags seem to work fine:
<c:if test="${lpc.verbose}">
...
</c:if>
However, I'm not sure if this is a best practice? Is there another way to achieve my goal?
Introduction
JSTL <c:xxx> tags are all taghandlers and they are executed during view build time, while JSF <h:xxx> tags are all UI components and they are executed during view render time.
Note that from JSF's own <f:xxx> and <ui:xxx> tags only those which do not extend from UIComponent are also taghandlers, e.g. <f:validator>, <ui:include>, <ui:define>, etc. The ones which extend from UIComponent are also JSF UI components, e.g. <f:param>, <ui:fragment>, <ui:repeat>, etc. From JSF UI components only the id and binding attributes are also evaluated during view build time. Thus the below answer as to JSTL lifecycle also applies to the id and binding attributes of JSF components.
The view build time is that moment when the XHTML/JSP file is to be parsed and converted to a JSF component tree which is then stored as UIViewRoot of the FacesContext. The view render time is that moment when the JSF component tree is about to generate HTML, starting with UIViewRoot#encodeAll(). So: JSF UI components and JSTL tags doesn't run in sync as you'd expect from the coding. You can visualize it as follows: JSTL runs from top to bottom first, producing the JSF component tree, then it's JSF's turn to run from top to bottom again, producing the HTML output.
<c:forEach> vs <ui:repeat>
For example, this Facelets markup iterating over 3 items using <c:forEach>:
<c:forEach items="#{bean.items}" var="item">
<h:outputText id="item_#{item.id}" value="#{item.value}" />
</c:forEach>
...creates during view build time three separate <h:outputText> components in the JSF component tree, roughly represented like this:
<h:outputText id="item_1" value="#{bean.items[0].value}" />
<h:outputText id="item_2" value="#{bean.items[1].value}" />
<h:outputText id="item_3" value="#{bean.items[2].value}" />
...which in turn individually generate their HTML output during view render time:
<span id="item_1">value1</span>
<span id="item_2">value2</span>
<span id="item_3">value3</span>
Note that you need to manually ensure the uniqueness of the component IDs and that those are also evaluated during view build time.
While this Facelets markup iterating over 3 items using <ui:repeat>, which is a JSF UI component:
<ui:repeat id="items" value="#{bean.items}" var="item">
<h:outputText id="item" value="#{item.value}" />
</ui:repeat>
...already ends up as-is in the JSF component tree whereby the very same <h:outputText> component is during view render time being reused to generate HTML output based on current iteration round:
<span id="items:0:item">value1</span>
<span id="items:1:item">value2</span>
<span id="items:2:item">value3</span>
Note that the <ui:repeat> as being a NamingContainer component already ensured the uniqueness of the client ID based on iteration index; it's also not possible to use EL in id attribute of child components this way as it is also evaluated during view build time while #{item} is only available during view render time. Same is true for an h:dataTable and similar components.
<c:if>/<c:choose> vs rendered
As another example, this Facelets markup conditionally adding different tags using <c:if> (you can also use <c:choose><c:when><c:otherwise> for this):
<c:if test="#{field.type eq 'TEXT'}">
<h:inputText ... />
</c:if>
<c:if test="#{field.type eq 'PASSWORD'}">
<h:inputSecret ... />
</c:if>
<c:if test="#{field.type eq 'SELECTONE'}">
<h:selectOneMenu ... />
</c:if>
...will in case of type = TEXT only add the <h:inputText> component to the JSF component tree:
<h:inputText ... />
While this Facelets markup:
<h:inputText ... rendered="#{field.type eq 'TEXT'}" />
<h:inputSecret ... rendered="#{field.type eq 'PASSWORD'}" />
<h:selectOneMenu ... rendered="#{field.type eq 'SELECTONE'}" />
...will end up exactly as above in the JSF component tree regardless of the condition. This may thus end up in a "bloated" component tree when you have many of them and they are actually based on a "static" model (i.e. the field does not ever change during at least the view scope). Also, you may run into EL trouble when you deal with subclasses with additional properties in Mojarra versions before 2.2.7.
<c:set> vs <ui:param>
They are not interchangeable. The <c:set> sets a variable in the EL scope, which is accessible only after the tag location during view build time, but anywhere in the view during view render time. The <ui:param> passes an EL variable to a Facelet template included via <ui:include>, <ui:decorate template>, or <ui:composition template>. Older JSF versions had bugs whereby the <ui:param> variable is also available outside the Facelet template in question, this should never be relied upon.
The <c:set> without a scope attribute will behave like an alias. It does not cache the result of the EL expression in any scope. It can thus perfectly fine be used inside for example iterating JSF components. Thus, e.g. below will work fine:
<ui:repeat value="#{bean.products}" var="product">
<c:set var="price" value="#{product.price}" />
<h:outputText value="#{price}" />
</ui:repeat>
It's only not suitable for e.g. calculating the sum in a loop. For that instead use EL 3.0 stream:
<ui:repeat value="#{bean.products}" var="product">
...
</ui:repeat>
<p>Total price: #{bean.products.stream().map(product->product.price).sum()}</p>
Only, when you set the scope attribute with one of allowable values request, view, session, or application, then it will be evaluated immediately during view build time and stored in the specified scope.
<c:set var="dev" value="#{facesContext.application.projectStage eq 'Development'}" scope="application" />
This will be evaluated only once and available as #{dev} throughout the entire application.
Use JSTL to control JSF component tree building
Using JSTL may only lead to unexpected results when being used inside JSF iterating components such as <h:dataTable>, <ui:repeat>, etc, or when JSTL tag attributes depend on results of JSF events such as preRenderView or submitted form values in the model which aren't available during view build time. So, use JSTL tags only to control flow of JSF component tree building. Use JSF UI components to control flow of HTML output generation. Do not bind the var of iterating JSF components to JSTL tag attributes. Do not rely on JSF events in JSTL tag attributes.
Anytime you think you need to bind a component to the backing bean via binding, or grab one via findComponent(), and create/manipulate its children using Java code in a backing bean with new SomeComponent() and what not, then you should immediately stop and consider using JSTL instead. As JSTL is also XML based, the code needed to dynamically create JSF components will become so much better readable and maintainable.
Important to know is that Mojarra versions older than 2.1.18 had a bug in partial state saving when referencing a view scoped bean in a JSTL tag attribute. The whole view scoped bean would be newly recreated instead of retrieved from the view tree (simply because the complete view tree isn't available yet at the point JSTL runs). If you're expecting or storing some state in the view scoped bean by a JSTL tag attribute, then it won't return the value you expect, or it will be "lost" in the real view scoped bean which is restored after the view tree is built. In case you can't upgrade to Mojarra 2.1.18 or newer, the work around is to turn off partial state saving in web.xml like below:
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
See also:
What's the view build time?
How does the 'binding' attribute work in JSF? When and how should it be used?
How to refactor snippet of old JSP to some JSF equivalent?
Should PARTIAL_STATE_SAVING be set to false?
Communication in JSF 2.0 - #ViewScoped fails in tag handlers
To see some real world examples where JSTL tags are helpful (i.e. when really properly used during building the view), see the following questions/answers:
How to make a grid of JSF composite component?
Create table columns dynamically in JSF
How to custom layout h:selectOneRadio
Conditional variable definition in JSF
How to make composite component similar to <h:selectOneRadio />
JSF 2 -- Composite component with optional listener attribute on f:ajax
Nested JSF Composite Components leading to a Stack Overflow exception
In a nutshell
As to your concrete functional requirement, if you want to render JSF components conditionally, use the rendered attribute on the JSF HTML component instead, particularly if #{lpc} represents the currently iterated item of a JSF iterating component such as <h:dataTable> or <ui:repeat>.
<h:someComponent rendered="#{lpc.verbose}">
...
</h:someComponent>
Or, if you want to build (create/add) JSF components conditionally, then keep using JSTL. It's way much better than verbosely doing new SomeComponent() in java.
<c:if test="#{lpc.verbose}">
<h:someComponent>
...
</h:someComponent>
</c:if>
See also:
Conditionally displaying JSF components
JSTL c:if doesn't work inside a JSF h:dataTable
Specify conditional rendering of element inside <ui:repeat>? The <c:if> does not seem to work
use
<h:panelGroup rendered="#{lpc.verbose}">
...
</h:panelGroup>
For switch-like output, you can use the switch face from PrimeFaces Extensions.

Resources