I have a set of data in array list form that I would like to display each food based on the menu category, but I cannot check with the logical operator eq in ELParser, please help me out of this
<ui:repeat var="menu" value="#{eventBean.menuList}">
<li><ol><h5>#{menu}</h5></ol></li>
<ui:repeat var="food" value="#{eventBean.projectDetail.foodList}">
<li>
<ui:fragment ></ui:fragment>
<ol><h:outputText rendered="#{food.menu eq menu}">#{food.name}</h:outputText></ol>
</li>
</ui:repeat>
</ui:repeat>
the menu can be display but the inner loop are not displaying any food. I had tried #{food.menu eq #{menu}} but will get exception on ELParser
EDIT 1:
I just realized that <h:outputText>#{food.name}</h:outputText> are basically cannot display the value, I must do <h:outputText value="#{food.name}"></h:outputText> in order to display value, my mistake.
Now I am searching for if condition to filter
I had tried JSTL c:if to make condition checking but didn't work out as expected, then I search through stack overflow this link has helped me out by implementing:
<ui:fragment rendered="#{food.menu eq menu}">#{food.name}</ui:fragment>
Depending on how complex your filtering needs to be I would go with basic jsf tags or a custom function
For a couple of options only :
<c:if test="#{condition}">do stuff</c:if>
For a limited number of options :
<c:choose>
<c:when test="#{condition1}">do stuff</c:when>
<c:when test="#{condition2}">do other stuff</c:when>
<c:otherwise>do something else</c:otherwise>
</c:choose>
for N Options look at the sollution here where you could use a custom EL function to do anything that a java function can do:
https://stackoverflow.com/a/7080174/2045820
Related
I am trying to conditionally build a custom list using <ui:repeat>. On every occurrence of -1 as item-value in list, I need to add a line break.
I tried to use <c:if> inside <ui:repeat> for that, but it does not seem to work. It always evaluates false.
<ul>
<ui:repeat value="#{topics.list}" var="topicId" >
<li>#{topicId}</li>
<c:if test="#{topicId eq -1}"> <br/> </c:if>
</ui:repeat>
</ul>
Is this possible?
Not with JSTL tags, no. They run during view build time, not during view render time. You can visualize it as follows: when JSF builds the view, JSTL tags run from top to bottom first and the result is a pure JSF component tree. Then when JSF renders the view, JSF components run from top to bottom and the result is a bunch of HTML. So, JSTL and JSF don't run in sync as you'd expect from the coding. At the moment your <c:if> JSTL tag tag runs, the #{topicId} variable which is set by <ui:repeat> JSF component isn't available in the scope.
Instead of using <c:if>, you need to specify the condition in the rendered attribute of the JSF component of interest. As you've actually none, you could wrap it in a <ui:fragment>.
<ul>
<ui:repeat value="#{topics.list}" var="topicId" >
<li>#{topicId}</li>
<ui:fragment rendered="#{topicId eq -1}"><br/></ui:fragment>
</ui:repeat>
</ul>
Alternatives are <h:panelGroup>
<h:panelGroup rendered="#{topicId eq -1}"><br/></h:panelGroup>
or in your specific case <h:outputText escape="false">
<h:outputText value="<br/>" escape="false" rendered="#{topicId eq -1}" />
as both also emits nothing else to the HTML output when no client side attributes are specified.
See also:
JSTL in JSF2 Facelets... makes sense?
Unrelated to the concrete problem, that's the wrong place for a <br/>. It would be ignored by any webbrowser respecting the HTML specification. Don't you mean it to be inside the <li>? Or better, give it a class and let CSS give it a margin-bottom.
I am using jsf primefaces. I want to display an image depending on the value of a specific outputext. If the text value is 'Alarm *' then a div will appear whith a spesific image. If the value is 'Alarm **' then a div with an other image will appear, etc. I tried the code below but it does not work for me.
<h:outputText id="alarmCriticalityValue" value="#{msg[summary.criticality.key]}" />
<c:if test="#{alarmCriticalityValue=='Alarm *'}">
<div class="alarm1"></div>
</c:if>
How should i implement this idea?
You need to use binding attribute to put the UIComponent instance in the EL scope. The id attribute doesn't do that, on contrary to what you expected.
<h:outputText binding="#{alarmCriticality}" ... />
And then you need to use UIOutput#getValue() to obtain its value attribute.
<c:if test="#{alarmCriticality.value == 'Alarm *'}">
That said, you'd better use rendered attribute here, particularly if #{summary} represents the currently iterated item of a JSF iterating component like <ui:repeat> or <h:dataTable>.
<h:panelGroup layout="block" styleClass="alarm1"
rendered="#{alarmCriticality.value == 'Alarm *'}" />
See also:
How does the 'binding' attribute work in JSF? When and how should it be used?
How to conditionally render plain HTML elements like <div>s?
JSTL in JSF2 Facelets... makes sense?
Unrelated to the concrete problem. It's strange to see the conditional rendering depend on localized text. What if you change the locale and/or the localized text? This is very brittle. You'd better check the bundle key instead.
<h:outputText value="#{msg[summary.criticality.key]}" />
<h:panelGroup layout="block" styleClass="alarm1"
rendered="#{summary.criticality.key == 'some.alarm.key'}" />
This way you also don't need to bind the output text anymore.
Try
<c:if test="#{msg[summary.criticality.key].equals('Alarm *')}">
Or add a binding to the h:outputText and check against that.
Try this
<h:outputText id="alarmCriticalityValue" value="#{msg[summary.criticality.key]}" />
<h:panelGroup layout="block" styleClass="alarm1" rendered="#{alarmCriticality.value eq 'Alarm *'}" />
I want to update an ui:param value or use something similar in ui:repeat loops with a condition. The idea is something as follows (is just an aprox, not the final implementation but I guess is understandable):
<ui:param name="marginLeftNode" value="#{myBean.initialMarginValue}" />
<ui:repeat value="#{myBean.viewWrapper.linkMap.entrySet().toArray()}" var="map">
<ui:repeat var="link" value="#{map.value}" varStatus="status">
<li style="margin-left: #{marginLeftNode}%" class="ico-#{link.getStyleCss()}-ayuda">
#{link.getTitle()}
</li>
<!-- Code conditions that doesn't works in any way as I've readed in the links after code -->
<c:if test="#{marginLeftNode gt 4}">
<ui:param name="marginLeftNode" value="#{myBean.viewWrapper.nodeList.get(status.index).depth}" />
</c:if>
<ui:fragment rendered="#{marginLeftNode gt 4}">
<ui:param name="marginLeftNode" value="#{myBean.viewWrapper.nodeList.get(status.index).depth}" />
</ui:fragment>
<!-- End code conditions: these are the two solutions c:if and ui:fragmen I tried -->
</ui:repeat>
</ui:repeat>
I can't use c:if inside ui:repeat because doesn't works (Specify conditional rendering of element inside <ui:repeat>? The <c:if> does not seem to work) and I can't use ui:fragment with ui:param because it doesn't works too (Conditional variable definition in JSF)
So, any idea how to solve that?
First of all, avoid of use JSTL if you can use JSF. Here is an answer that explains how JSTL and JSF are executed in different steps -> https://stackoverflow.com/a/3343681/4253629
To redefine conditionally a ui:param, for example, you can do this:
<ui:param
name="marginLeftNode"
value="#{marginLeftNode gt 4 ? myBean.viewWrapper.nodeList.get(status.index).depth : marginLeftNode }"/>
Probably exists another solution, but this works.
Greetings
Changing the ui:param inside the loop has no real value. The real purpose of a ui:param is to pass runtime variables into a template client or included file. By the time your parameter has been passed in, there's little value in changing it. If all you want is to conditionally alter the value of the variable after it's been passed, you could just use JSTL's c:set to set a page-scoped variable that you could then use
<ui:repeat value="#{myBean.viewWrapper.linkMap.entrySet().toArray()}" var="map">
<ui:repeat var="link" value="#{map.value}" varStatus="status">
<li style="margin-left: #{marginLeftNode}%" class="ico-#{link.getStyleCss()}-ayuda">
#{link.getTitle()}
</li>
<c:if test="#{marginLeftNode gt 4}">
<c:set var="marginLeftNode" value="#{myBean.viewWrapper.nodeList.get(status.index).depth}"/>
</c:if>
</ui:repeat>
You could then access your set variable as #{marginLeftNode} anywhere within that view
I have a JSF composite component which renders only some parts based on the attribute cc.attrs.list passed to it.
In one of the components I want to update a set of other components based on the attribute. So something like this:
<p:ajax event="dialogReturn" listener="#{cc.listener}"
update="#{cc.attrs.id2}_input #{cc.attrs.id2}_resultTable"/>
The problem is that the resultTable is not rendered all the time and when the resultTable is not there, I get an exception Cannot find component with expression "id_resultTable", which is not surprising. So my idea was to create a variable which will contain id of the attribute or empty String like this:
<c:if test="#{cc.attrs.list}">
<ui:param name="updateTable" value="#{cc.attrs.id2}_resultTable"/>
</c:if>
<c:otherwise>
<ui:param name="updateTable" value=""/>
</c:otherwise>
and then do the ajax update like this:
<p:ajax event="dialogReturn" listener="#{cc.listener}"
update="#{cc.attrs.id2}_input #{updateTable}"/>
The problem is, that the #{updateTable} variable is always an empty String(I've tried to put it as a content of outputText) and I have no idea why.
You can just omit the ui:param and do the check directly in the p:ajax:
<p:ajax event="dialogReturn" listener="#{cc.listener}"
update="#{cc.attrs.id2}_input #{cc.attrs.list ? cc.attrs.id2.concat('_resultTable') : ''}"/>
A problem with the c:if-approach could be, that when you update this section via ajax the condition is not re-checked as JSTL-tags are evaluated at view build time. Have a look at JSTL in JSF2 Facelets... makes sense? for further information.
This is not really a solution, but I've done a workaround for the problem which works. I've added h:panelGroup with id around the table and I'm updating this instead of the table.
I am trying to conditionally build a custom list using <ui:repeat>. On every occurrence of -1 as item-value in list, I need to add a line break.
I tried to use <c:if> inside <ui:repeat> for that, but it does not seem to work. It always evaluates false.
<ul>
<ui:repeat value="#{topics.list}" var="topicId" >
<li>#{topicId}</li>
<c:if test="#{topicId eq -1}"> <br/> </c:if>
</ui:repeat>
</ul>
Is this possible?
Not with JSTL tags, no. They run during view build time, not during view render time. You can visualize it as follows: when JSF builds the view, JSTL tags run from top to bottom first and the result is a pure JSF component tree. Then when JSF renders the view, JSF components run from top to bottom and the result is a bunch of HTML. So, JSTL and JSF don't run in sync as you'd expect from the coding. At the moment your <c:if> JSTL tag tag runs, the #{topicId} variable which is set by <ui:repeat> JSF component isn't available in the scope.
Instead of using <c:if>, you need to specify the condition in the rendered attribute of the JSF component of interest. As you've actually none, you could wrap it in a <ui:fragment>.
<ul>
<ui:repeat value="#{topics.list}" var="topicId" >
<li>#{topicId}</li>
<ui:fragment rendered="#{topicId eq -1}"><br/></ui:fragment>
</ui:repeat>
</ul>
Alternatives are <h:panelGroup>
<h:panelGroup rendered="#{topicId eq -1}"><br/></h:panelGroup>
or in your specific case <h:outputText escape="false">
<h:outputText value="<br/>" escape="false" rendered="#{topicId eq -1}" />
as both also emits nothing else to the HTML output when no client side attributes are specified.
See also:
JSTL in JSF2 Facelets... makes sense?
Unrelated to the concrete problem, that's the wrong place for a <br/>. It would be ignored by any webbrowser respecting the HTML specification. Don't you mean it to be inside the <li>? Or better, give it a class and let CSS give it a margin-bottom.