JSF Map binding in Repeater - java

Here is what I am trying to do:
<ui:repeat value="#{foo}" var="keyprefix">
<p:inputText value="#{someBean.someMap[keyprefix + 'somesuffix']}" />
</ui:repeat>
I have tried using fn:join which doesn't work. I tried using .concat() but I am not on 2.2, I'm still using 2.1. Is there a simple way to do this I'm missing?

You can use <c:set> to prepare the dynamic map key by just inlining the EL expression in the string literal the usual way.
<c:set var="key" value="#{keyprefix}somesuffix" />
<p:inputText value="#{someBean.someMap[key]}" />

Related

PrimeFaces filling dataTable with List<Object> inside another List<Object>

UPDATE:
I found that the issue with the dataGrid not looping through a list inside a list was an issue on the XML code side. Now the dataGrid is reading the List and looping through it creating panels based on the name. The issue now seems to be accessing certain properties in this List.
<p:dataGrid value="#{objList.objList2}" var="objList2" columns="1">
<p:panel id="obj2" header="#{objList2.name}" toggleable="true" collapsed="false">
<h:panelGrid columns="2" style="width: 100%" columnClasses="scenario-viewer-leftcolumn,scenario-viewer-rightcolumn">
<h:outputText value="Output Name:" />
<p:inputText value="#{objList2.objType}" styleClass="textBoxStyle"/>
<h:outputText value="Output Bool:" />
<p:selectBooleanCheckbox value="#{objList2.boolVar}"/>
</h:panelGrid>
</p:panel>
</p:dataGrid>
</p:panel>
</p:dataGrid>
When I try to access a variable under objList2 is gives me the error saying The class obj2 does not have a readable property 'objType'. I double checked and it does have this property/variable and it is initialized.
What makes this even more strange is if I use objList2.boolVar in place of objList2.name in the header for each panel, it displays the information fine. This proves that the property exists and is initialized. Why wouldn't this work in inputText?? Any help would be greatly appreciated.
ORIGINAL:
I am working with PrimeFaces and trying to create a xhtml form for my UI. I am trying to dynamically display data from a list into a dataGrid structure. I am able to do this successfully, but I also need to display data from a list inside the first list.
For example:
I have a List under the variable objList which I use for my first dataGrid. I am able to loop through this list and create panels for each object and some other String data per object.
<p:dataGrid value="#{scenarioTree.objList}" var="objList" columns="1">
<p:panel id="obj" header="#{objList.name}" toggleable="true" collapsed="true">
<h:panelGrid columns="2" style="width: 100%" columnClasses="scenario-viewer-leftcolumn,scenario-viewer-rightcolumn">
<h:outputText value="text:" />
<p:inputText value="#{objList.variable}" styleClass="textBoxStyle"/>
<h:outputText value="text2:" />
<p:inputText value="#{objList.variable2}" styleClass="textBoxStyle"/>
</h:panelGrid>
Now I want to be able to create a second dataGrid that refers to objList2 which is inside objList1. Doing this though returns No records found in the UI even though there is a bunch of records there.
<p:dataGrid value="#{objList.objList2}" var="objList2" columns="1">
<p:panel id="obj2" header="#{objList2.name}" toggleable="true" collapsed="false">
</p:panel>
</p:dataGrid>
</p:panel>
</p:dataGrid>
Is this a bug with PrimeFaces or am I not able to do this? Or am I doing this wrong?
whenever we are talking about iterating list in xhtml we have dataTable,dataGrid, etc and panelGrid also becoz dataTable and all others are child of panelGrid(we can say this becoz panelGrid is also going to form table and others as well i meant child from this way) so in this case try to iterate the inner list in panelGrid since you are using panelGrid and referring variable is list so internally jsf is going to understand like this:
objList.get(i).getVariable();//For the first row
but according to your code it is understanding like this:
objList.getVariable();
which is not at all present so it is giving issue take out panel i don't find it's use and use like this:
<p:panelGrid value="#{objList}" var="obj">
//Access properties inside that
</p:panelGrid>
you can use <f:facet> tag if you want something in header

JSF <ui:include /> Recursion Causes java.lang.StackOverflowError

I have, what I would assume, is a pretty common use case. We're rendering a simple "Comments" page using JSF on Wildfly 10.0. Each comment may have a parent comment, and child comments underneath it. Since there's no way to know ahead of time what the structure is, we'd like to create a JSF fragment and <ui:include /> it recursively to render the contents. It would look something like this...
Main page:
<ul class="comments>
<ui:repeat value="#{myObj.comments}" var="comment">
<ui:include src="/WEB-INF/fragments/comment.xhtml">
<ui:param name="comment" value="#{comment}" />
</ui:include>
</ui:repeat>
</ul>
Comment Fragment:
<li><h:outputText value="#{comment.text}">
<ui:fragment rendered="#{not empty comment.childComments}">
<ul class="comments">
<ui:repeat value="#{comment.childComments}" var="comment">
<ui:include src="/WEB-INF/fragments/comment.xhtml">
<ui:param name="comment" value="#{comment}" />
</ui:include>
</ui:repeat>
</ul>
</ui:fragment>
</li>
However, when I run this code, the recursion seems to cause java.lang.StackOverflowError, regardless of how many items there are. Additionally, we see a javax.servlet.ServletException saying, "Could not Resolve Variable [Overflow]"
Is there a reason why this recursive call results in this Exception? Is there a better way to accomplish this? I've tried using <c:forEach /> to iterate over the comments, however when I do this it does not appear to work in JSF. I've tried both the http://xmlns.jcp.org/jsp/jstl/core and http://java.sun.com/jsp/jstl/core namespaces for the taglib, but the <c:forEach /> tag doesn't seem to iterate over my objects. (That is, nothing is being rendered to the page)
Any help you can give would be GREATLY appreciated.

How to use jstl el to call a dynamic nested property

if you wanna call the getter method from a specific bean using a dynamic key you use like that:
${bean[getterName]}
but if you wanna call double nested, or triple nested properties with a dynamic name how does it works, is it possible?
${bean.propertyA.propertyB} WORKS
${bean[propertyA.propertyB]} DOES NOT WORKS
<c:set var="dynamicKey" value="propertyA.propertyB" />
${bean[dynamicKey]} DOES NOT WORKS
UPDATE:
For now we're handling like that:
<c:forTokens items="${property}" delims="." var="item">
<c:set var="value" value="${value[item]}" />
</c:forTokens>
Dot notation vs brackets notation with nested properties:
${bean.propertyA.propertyB}
${bean[propertyA.propertyB]} ==> Not right, instead
${bean["propertyA"]["propertyB"]}
Your example with JSTL:
<c:set var="dynamicKey" value="${bean['propertyA']['propertyB']}" />
<c:out value="${dynamicKey}" />
After 2 years we are leaving like this since it does not seems to have a big impact on performance.
<c:forTokens items="${property}" delims="." var="item">
<c:set var="value" value="${value[item]}" />
</c:forTokens>

Primefaces / JSF: selectOneMenu value is not set, ajax listener not called

I am using Primefaces and JSF to develop this frontend. My issue is that one of my selectonemenus never sets its value binding, "selectedGroup", so the second dropdown is never populated. My backing bean is being called to "update" the second selectonemenu, but the listener of that ajax is not called, nor is selectedGroup ever set. This code is effectively identical to the Showcase for "Select". I even verified that the showcase code works from scratch (which i did not doubt), but fail to see how my situation is any different from that example.
Other stackoverflow questions on this topic indicate that something was left out, but none of those suggestions matched my issue.
I have two selectOneMenus, like so.
<h:form id="outerForm">
<p:panel id="outerPanel">
<p:panelGrid id="outerPanelGrid">
<h:outputLabel for="groupSelection" value="Group: "/>
<p:selectOneMenu id="groupSelection" value="#{myBean.selectedGroup}" >
<p:ajax update="commandSelection"
listener="#{myBean.handleGroupSelection}" />
<f:selectItem itemLabel="---Please Select Group---" itemValue=""/>
<f:selectItems var="group" value="#{myBean.groups}"
itemLabel="#{group.name}" itemValue="#{group.name}" />
</p:selectOneMenu>
<h:outputLabel for="commandSelection" value="Command: "/>
<p:selectOneMenu id="commandSelection" value="#{myBean.command}">
<f:selectItems value="#{myBean.commandStringsList}"/>
</p:selectOneMenu>
</p:panelGrid>
</p:panel>
</h:form>
This page is being displayed in the "center" portion of my layout template like so..
<ui:define id="content" name="content">
<p:panel id="contentPanel" style="float:left; border:none">
<ui:include src="#{anotherBean.currentView}.xhtml"/>
</p:panel>
</ui:define>
The backing bean DOES use some data classes to contain some of the data which is populated, but I thought i was doing everything correct to map it into the view. For the most part, I am using Strings, though.
Does anyone see what I am missing? At the very least, is this xhtml valid?
I should also mention that this page was working before I created and used a template. Basically, I was rendering it in a tab of a tabview using ui:include in the body of index.xhtml. Though I did not notice initially, this page stopped working sometime after I incorporated the template (poor testing on my part, I know).
<f:selectItems var="group" value="#{myBean.groups}"
itemLabel="#{group.name}" itemValue="#{group.name}" />
you can't specify selectItems this way. translation has to be bidirectional. use a converter!
<f:selectItems var="group" value="#{myBean.groups}"
itemLabel="#{group.name}" itemValue="#{group}"
converter="groupConverter"/>

Resolving facelets components at runtime

do you know a way to select a different facelets component at runtime?
I've got some of code similar to this:
<s:fragment rendered="#{r== 'case1'}">
<div>
<ui:include src="case1.xhtml" />
</div>
</s:fragment>
<s:fragment rendered="#{r== 'case2'}">
<div>
<ui:include src="case2.xhtml" />
</div>
</s:fragment>
I'd like to write
<ui:include src="#{r}.xhtml" />
Thanks.
Your solution should work OK - the src attribute can be a literal or an EL expression. You might want to make the expression use a managed bean property or resolve it through a function. That way, you can ensure that it is never null (you could return a reference to an empty page if it was). You'll probably get a 404 error if #{r} resolves to null.
<ui:include src="#{myfn:resolveNotNull(r, 'pageIfRIsNull')}.xhtml" />
Not sure. An alternative though would be to use a template with a ui:insert and then direct to case1 or case2 which use ui:define programatically.
It is possible to have selective use of ui:include with other JSF components. Example:
<h:panelGroup rendered="#{!menuMBean.passwordResetRequired}">
<ui:include src="homeNormal.xhtml" />
</h:panelGroup>

Categories