<pe:keyFilter > not working in <ui:repeat>. Throwing Exception for id not found - jsf

<pe:keyFilter> is working with single <p:inputText> but when i go for inputText in repeat it is not working and throwing an exception.
Like
<p:inputText value="text2" id="text2" />
<pe:keyFilter for="text2" regEx="/[ABC]/i"/>
It is working fine but below code is not working and throwing exception for id text-0 not found
<ui:repeat var="answer" value="#{answerBean.answerList}" varStatus="answerStatus" >
<p:inputText value="#{answer.answerText}" id="text-#{answerStatus.index}" />
<pe:keyFilter for="text-#{answerStatus.index}" regEx="/[ABC]/i" />
</ui:repeat>

You don't need to worry about forcing unique IDs inside JSF iteration components. JSF already does that all by itself. Simply get rid of varStatus and all unnecessity related to that and let JSF do its job.
<ui:repeat value="#{answerBean.answerList}" var="answer">
<p:inputText id="text" ... />
<pe:keyFilter for="text" ... />
</ui:repeat>
It's only necessary if you were using <c:forEach> taghandler instead of <ui:repeat> component. See also JSTL in JSF2 Facelets... makes sense?

Related

<c:choose><c:when> in JSF page does not work, seems to always evaluate false

In my JSF page I use <c:choose><c:when> tag to conditionally display content. However, it does not work as it seems to always evaluate false.
E.g.
<h:outputText value="#{pollInfo.active} -" />
<c:choose>
<c:when test="#{pollInfo.active}">
<h:outputText value="Active" />
</c:when>
<c:otherwise>
<h:outputText value="Deactive" />
</c:otherwise>
</c:choose>
There are for sure a few items with active=true, which is confirmed by <h:outputText>, but it just prints Deactive for all items. You can see the actual output in the following picture:
How is this caused and how can I solve it?
The symptoms and the screenshot suggests that the #{pollInfo} represents the currently iterated item of an iterating UI component such as <ui:repeat>, <h:dataTable>, <p:tabView>, <p:dataTable>, etc.
JSTL tags run during view build time, that moment when JSF component tree is built based on XHTML source code. The var attribute of such an iterating UI component is only available during view render time, that moment when HTML output is produced based on JSF component tree.
In other words, they don't run "in sync". The #{pollInfo} is always null during view build time.
In this particular case, you need the JSF component's rendered attribute instead.
<h:outputText value="Active" rendered="#{pollInfo.active}" />
<h:outputText value="Deactive" rendered="#{not pollInfo.active}" />
Or if you intend to conditionally render larger pieces of code, wrap all in a <ui:fragment>:
<ui:fragment rendered="#{pollInfo.active}">
<h:outputText value="Active" />
<!-- Some more components here if necessary. -->
</ui:fragment>
<ui:fragment rendered="#{not pollInfo.active}">
<h:outputText value="Deactive" />
<!-- Some more components here if necessary. -->
</ui:fragment>
Again another alternative, given that you've a pure if-else, is using the conditional operator in EL:
<h:outputText value="#{pollInfo.active ? 'Active' : 'Deactive'}" />
Additional bonus is, you end up with much less code.
See also:
JSTL in JSF2 Facelets... makes sense?

Is it possible to use <c:if> inside <a4j:repeat>

Is it possible to use <c:if> inside <a4j:repeat>?
I need to render a <br /> each 4 elements. I tried the following approach:
<a4j:repeat value="#{MBean.sucursal.events}" var="item" rowKeyVar="idx" >
<h:outputText value="#{item.eventDescription}" id="item1" />
<c: if test=#{idx % 4 == 0}>
<br />
</c:if>
</a4j:repeat>
However, it does not render the <br /> elements at all.
How can I achieve the requirement anyway?
Note: I'll ignore the careless formulation of the code which causes that it wouldn't compile/run properly at all. There's a space in <c :if> and the quotes are missing from the <c:if test> attribute. In future questions please pay a bit more attention to the properness of the code snippets you post, otherwise you'll only get invalid answers due to those red herrings.
Coming back to your concrete problem, this construct will indeed fail. The <c:if> runs during view build time (when the JSF component tree is about to be populated based on Facelets/JSP files), while the <a4j:repeat> runs during view render time (when the HTML code is about to be generated based on the JSF component tree). So, at the moment the <c:if> runs, #{idx} does not exist in the scope at all and always evaluates to null.
There are basically 2 solutions:
Use <c:forEach> instead of <a4j:repeat> to iterate over the items. It runs during view build time, so it'll run "in sync" with <c:if>.
<c:forEach items="#{MBean.sucursal.events}" var="item" varStatus="loop">
<h:outputText value="#{item.eventDescription}" id="item#{loop.index}" />
<c:if test="#{loop.index % 4 == 0}">
<br />
</c:if>
</c:forEach>
(note that I changed the <h:outputText id> as well, otherwise you end up with duplicate component ID errors or malformed HTML; feel free to omit the id attribute altogether, JSF will autogenerate proper one)
Use JSF component's rendered attribute instead of <c:if> to conditionally render HTML. It runs during view render time, so it'll run "in sync" with <a4j:repeat>.
<a4j:repeat value="#{MBean.sucursal.events}" var="item" rowKeyVar="idx">
<h:outputText value="#{item.eventDescription}" id="item1" />
<h:panelGroup rendered="#{idx % 4 == 0}">
<br />
</h:panelGroup>
</a4j:repeat>
See also:
JSTL in JSF2 Facelets... makes sense?

<c:foreach> tag not evaluating an object

I have the following piece of code:
<h:outputText value="#{lecture.lectureName}" />
<c:forEach items="#{criterionController.getCriteriaForLecture(lecture)}" var="criterion">
<h:outputText value="#{criterion.criterionName}" />
<h:commandLink value="Edit"/>
<h:commandLink value="Delete"/>
</c:forEach>
The output text part is working perfectly and displays what it should display so this proves that the lecture object is set. However the for each tag gives a null pointer exception. When I debugged the code, I saw that the lecture object was taken as null when the method getCriteriaForLecture() was called.
How can this behaviour explained?
This can happen if the lecturer variable is in turn been set by a JSF iterating component such as <h:dataTable>, <ui:repeat>, etc or probably a <p:tabView>, based on your previous question.
A more detailed explanation of this behaviour can be found here: JSTL in JSF2 Facelets... makes sense? To the point, JSTL tags runs during building the view, not during rendering the view. The lecturer variable is in your particular case only available during rendering the view and is thus always null during building the view, when JSTL runs.
To solve it, use a normal JSF component like <ui:repeat> instead.
<ui:repeat value="#{criterionController.getCriteriaForLecture(lecture)}" var="criterion">
<h:outputText value="#{criterion.criterionName}" />
<h:commandLink value="Edit"/>
<h:commandLink value="Delete"/>
</ui:repeat>
Much better would be not doing business actions in getters at all. Just make the List<Criterion> a property of Lecture instead.
<ui:repeat value="#{lecture.criterions}" var="criterion">
<h:outputText value="#{criterion.criterionName}" />
<h:commandLink value="Edit"/>
<h:commandLink value="Delete"/>
</ui:repeat>
See also Why JSF calls getters multiple times

Setting <f:param> value with <ui:repeat> var

<h:form>
<ui:repeat value="#{sampleManagedBean.food}" var="food">
<h:commandLink value="Name" action="#{sampleManagedBean.outcome}">
<f:param name="name" value="ssd" />
<f:param name="v" value="#{food.boy}" />
</h:commandLink>
<h2>#{food.boy}</h2>
</ui:repeat>
</h:form>
I can't get the the second <f:param> value which is set based on <ui:repeat var>. I can get only the first one which is hardcoded.
The ui:repeat is an UI component while f:param is a taghandler (like JSTL). Taghandlers run during view build time before UI components which run during view render time
(see here).
In our case it means that in the view build phase f:param knows nothing about #{food.boy}. c:forEach will be fine, but if we call some kind of ajax action to change the size of#{sampleManagedBean.food} and rerender the form, we'll not see any changes on page. Because partial rerendering (ajax) affects only UI component tree. c:forEach is somewhere between hardcoding and ui:repeat, we'll have to reload the page to see changes.
try this way,
<h:form>
<ui:repeat value="#{sampleManagedBean.food}" var="food">
<h:commandLink value="Name" action="#{sampleManagedBean.outcome}">
<f:setPropertyActionListener value="ssd" target="#{sampleManagedBean.name}" />
<f:setPropertyActionListener value="#{food.boy}" target="#{sampleManagedBean.v}" />
</h:commandLink>
</ui:repeat>
</h:form>

JSTL c:if doesn't work inside a JSF h:dataTable

I'm trying to use <c:if> to conditionally put a <h:outputLink> inside a <h:dataTable> when the state is finished.
<h:dataTable value="#{bean.items}" var="item" width="80%">
<h:column>
<f:facet name="header">
<h:outputText value="State" />
</f:facet>
<c:if test="#{item.state != 'Finish'}">
<h:outputText value="Missing value" />
</c:if>
<c:if test="#{item.state == 'Finish'}">
<h:outputLink value="myLink">
<h:outputText value="Value = #{item.state}" />
</h:outputLink>
</c:if>
</h:column>
</h:dataTable>
But this does not work, why is that and how can I fix it?
JSTL tags are evaluated during building of the view, not during rendering of the view. You can visualize it as follows: Whenever a view tree get created for the first time, all JSTL tags are executed and the result is a view with only JSF components. Whenever a view tree get rendered, all JSF components get executed and the result is HTML. So: JSF+JSTL doesn't run in sync as you'd expect from the coding. JSTL runs from top to bottom first, hands the result to JSF and then it's JSF's turn to run from top to bottom again. This may lead to unexpected results in JSF iterating components like UIData because the row data (in your particular case the #{item} object) is not available while JSTL runs.
In a nutshell: Use JSTL to control flow of JSF component tree building. Use JSF to control flow of HTML output generation.
You want to use the rendered attribute here.
<h:outputText value="Missing value" rendered="#{item.state ne 'Finish'}" />
<h:outputLink value="myLink" rendered="#{item.state eq 'Finish'}">
<h:outputText value="Value = #{item.state}" />
</h:outputLink>
See also:
JSTL in JSF2 Facelets... makes sense?
Conditionally displaying JSF components

Resources