c:forEach not iterating through list in a TabView - jsf

I have been trying to iterate through a list of tabs (my own custom tab object) by using c:forEach tag. But when I run the code, the tabs are not getting displayed. The page has no tabs.
When I debugged the code, I found that the getter method for the list object in the c:forEach items is not getting called. Please refer the below xhtml code:
<p:tabView id="tabView" dynamic="true" cache="false">
<p:ajax event="tabChange" listener="#{tabsController.onTabChange}" />
<c:forEach items="#{menusController.tabs}" var="customTab" varStatus="loop">
<p:tab title="#{customTab.title}" >
<f:subview id="tab_#{loop.index}">
<ui:include src="#{customTab.pageName}" />
</f:subview>
</p:tab>
</c:forEach>
</p:tabView>
I tried to follow the solution in this post JSF dynamically include src in "ui:include src="#{bean.pagePath}" but still it didn't work.

You should not mixing JSP and JSF tags, c:forEach is executing before JSF parser, instead use ui:repeat.

Related

c:forEach inside p:tab does not work

I am using primefaces 6, JSf2.0, jstl 1.2 on Weblogic server.
I have an xhtml page where i want to display panels dynamically inside a Tab. The panels should behave like a Dashboard, so i have put the panels inside a dashboard tag.
My problem is that c:forEach is not able to get values from the items I want to iterate. It is confirmed that my "items="${cg.charts}" is of List type and does have objects, but the panels dont appear in UI, as well as there are not exception raised. Any leads ?
<p:tabView id="tabViewId"
value="#{userdashboard.chartGroupsList}" var="cg" onTabShow="reflowChart()" >
<p:tab title="#{cg.groupName}" >
<p:dashboard model="#{userdashboard.model}" >
<p:ajax event="reorder" listener="#{userdashboard.handleReorder}" />
<c:forEach var="c" items="${cg.charts}">
<p:panel id="pnlDivId#{c.id}" header="#{c.name}">hello</p:panel>
</c:forEach>
</p:dashboard>
</p:tab>
</p:tabView>

PrimeFaces p:accordionPanel inside ui:repeat or c:forEach

I'm trying to create multiple accordionPanels.
I tried to include this tag inside repeat elements (e.g. c:forEach).
The accordionPanel is well rendered, but I'm unable to switch from one tab to another.
These are some codes I tried:
<ui:repeat value="#{myBackingBean.myList}" var="o">
<p:accordionPanel dynamic="true" cache="true" multiple="true" widgetVar="accordion">
<p:tab title="Title 1">
#{o.data_one}
</p:tab>
<p:tab title="Title 2">
#{o.data_two}
</p:tab>
</p:accordionPanel>
</ui:repeat>
And also
<c:forEach items"${myBackingBean.myList}" var="o">
<p:accordionPanel dynamic="true" cache="true" multiple="true" widgetVar="accordion">
<p:tab title="Title 1">
#{o.data_one}
</p:tab>
<p:tab title="Title 2">
#{o.data_two}
</p:tab>
</p:accordionPanel>
</ui:repeat>
Both of these codes produces a list of accordionPanels, each with two tabs.
But I'm unable to switch from one tab to another: If I click one tab it does not open nor close (except for the last accordionPanel).
Noteworthy, if I put two or more accordionPanels by hand (without JSF loops) they works.
Also, I've checked the requests the browser sends when I try to open/close a tab. The requests I intercept are like:
<?xml version="1.0" encoding="utf-8"?><partial-response><changes><update id="mainForm:tabView"><![CDATA[
// something that always use the id of the HTML tag of the _last_ accordionPanel
</update></changes></partial-response>
How can I put an <accordionPanel> inside an <ui:repeat> or <c:forEach> so that I can still switch the accordionPanel's tab?
Its the problem with the widgetVar when you put p:accordion in ui:repeat, it will generate Accordion Panel components with different/dynamic Ids but not with different/dynamic widgetVar when you explicitly specify widgetVar like you're doing in your code.
Which is basically name to Javascript Object to access the Client side Api functions of p:accordion.
So If you are not using that widgetVar of p:accordions anywhere, Remove widgetVar attribute, then the widgetVar will be generated dynamically.
If you still want to use widgetVar, give dynamic name yourself, for example:
widgetVar="accordion_#{o.data_one}"
Note: I tried the above strategy with only on ui:repeat.
Using:Primefaces 3.5 and JSF 2.1.13 and its working for me.

JSF dynamically include src in "ui:include src="#{bean.pagePath}"

I tried to include multiple source page path using ui:include tag in different tabs. The problem is when i gave the source page path as static one means that page will be shown but if give the source page path from backing bean mean it won't include the page.
Here is my code
template.xhtml:
<p:layoutUnit position="center" id="layoutCenter">
<h:form id="tempFormId">
<p:tabView value="#{multiTabBean.tabsList}" var="useCase"
activeIndex="#{multiTabBean.activeTabIndex}">
<p:tab title="#{useCase.title}" closable="true">
<f:subview>
<h:panelGroup id="mainTempPanelGroupId" layout="block">
<ui:include src="#{useCase.path}" />
</h:panelGroup>
</f:subview>
</p:tab>
</p:tabView>
</h:form>
</p:layoutUnit>
bean:
public String menuAction() {
menuBtnRendered = true;
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
selectedModuleViewId = externalContext.getRequestParameterMap().get(
"moduleViewId");
tabsList.add(new Tab(getTabId(selectedModuleViewId),
selectedModuleViewId, getModulePath(selectedModuleViewId)));
return null;
}
I'm using #ViewScoped.
<ui:include> runs during view build time (when XHTML is turned into JSF component tree). <p:tabView> runs during view render time (when JSF component tree needs to produce HTML).
So, <p:tabView var> isn't available when <ui:include> runs. This problem is detailed in this answer: JSTL in JSF2 Facelets... makes sense? (<ui:include> is a taghandler and has hence same lifecycle as JSTL tags).
You can solve this to a certain degree by using <c:forEach> to produce <p:tab>s instead of <p:tabView value>.
<p:tabView activeIndex="#{multiTabBean.activeTabIndex}">
<c:forEach items="#{multiTabBean.tabsList}" var="useCase" varStatus="loop">
<p:tab title="#{useCase.title}" closable="true">
<f:subview id="tab_#{loop.index}">
<h:panelGroup id="mainTempPanelGroupId" layout="block">
<ui:include src="#{useCase.path}" />
</h:panelGroup>
</f:subview>
</p:tab>
</c:forEach>
</p:tabView>
It's by the way interesting to see that you somehow used <f:subview> in your initial attempt which is completely useless over there (already taken into account by <p:tabView var>), but it's actually helpful in here (it creates a new NamingContainer around the tab content).
The above Community's answer hasn't worked for dynamic tabView
<p:tabView dynamic="true" ...
If i use dynamic="true" and c:foreach for tabs, when i add or remove a tab, do update #tabViewId, the tabview will reload "All content of existed tabs" => this is not the way to attribute "dynamic" work, it's not lazy.
My project has a problem with this, i had to customize the method encodeEnd of TabViewRenderer and do something else, but it's not simple.
I wondering whether there is a way to include XHTML templates at rendered time?

Dynamic Primefaces:tabView doesn't update

I'm using Primefaces 3.4 (also tried 3.3) and Mojarra 2.1.7. But I have a problem updating my dynamical tabs within a p:tabView.
I have 2 buttons which should add an additional tab. The first button is outside the p:tabView. When clicking this button, the backing bean is called, the p:tabView is updated, and the new tab is shown. But when I click the second button, which is inside a tab of that tabView, the backing bean is called, but the tabView is NOT updated.
This lack of updating occures only in dynamic tabs. When I modify the given example to have only one tab, and displaying a value which changes when clicking the buttons, the tabView is updated by both buttons, and the new Value is shown. So it is an problem only occuring in dynamic tabs.
Here is my code.
<f:view contentType="text/html">
<h:form>
<p:commandButton value="press me" action="#{idTestBean.addTab}" update=":ApplicationTab"/>
</h:form>
<p:tabView id="ApplicationTab" cache="false" dynamic="false" var="tab" value="#{idTestBean.tabList}">
<p:tab title="tab" closable="false" >
<p:panel>
<h:form>
<p:commandButton value="press me" action="#{idTestBean.addTab}" update=":ApplicationTab"/>
</h:form>
#{idTestBean.count}
</p:panel>
</p:tab>
</p:tabView>
</f:view>
The different tabs contains separate forms that needed to be submitted separate. therefore I had the approach of more than one form.
Well this must do the trick:
<f:view contentType="text/html">
<h:form>
<p:commandButton value="press me" action="#{idTestBean.addTab}" update="#form"/>
<p:tabView id="ApplicationTab" cache="false" dynamic="false" var="tab" value="#{idTestBean.tabList}">
<p:tab title="tab" closable="false" >
<p:panel>
<p:commandButton value="press me" action="#{idTestBean.addTab}" update="#form"/>
#{idTestBean.count}
</p:panel>
</p:tab>
</p:tabView>
</h:form>
</f:view>
Today i did the same problem too, I had a dynamic tabview, and inside tabs, there're some panels that needed to be updated when tab changes, so what i did was, i added the p:ajax on event TabChange, and in the update attribute, i added the form id and tabviewId like this:
:formID:tabViewID
and it worked at last.
Just so you know.

ui:repeat inside composition not printing values

I am new to jsf. I have the bellow code. When I place ui:repeat inside rich:toolbar it prints the data. But when I place it after the toolbargroup inside composition tag it doesn't print anything. I have a toolbar and I want to show ui:repeat data bellow that toolbar. If I place it in toolbar it shows the data but inside the toolbar not bellow it. How can I place it bellow the toolbar?
Thanks.
Update: I found out the problem. The ui:repeat tag is showing up bellow the toolbar. So how can I add position to ui:repeat?
enter code here<h:body>
<ui:composition> <h:panelGroup layout="block">
<a4j:region>
<rich:toolbar id="header-toolbar" height="30px" itemSeparator="line">
<rich:toolbarGroup location="right" rendered="#{not empty searchType}">
<rich:menuItem
label="search"
mode="ajax"
execute="#this"
oncomplete="#{rich:component(searchFormModalPanel)}.show();"
status="status"/>
</rich:toolbarGroup> </rich:toolbarGroup>
</rich:toolbar>
</a4j:region> //Bellow doesn't show up! <ui:repeat value="#{breadCrumbMB.crumbs}" var="crumb" varStatus="crumStatus">
#{breadCrumbMB.incIndex()}
<h:outputLink value="#{crumb}">
<h:outputText value="#{breadCrumbMB.title(crumb.toString())}" rendered="${breadCrumbMB.lastLink()=='false'}"/></h:outputLink> >
<h:outputText value="#{breadCrumbMB.title(crumb.toString())}" rendered="${breadCrumbMB.lastLink()=='true'}"/>
</ui:repeat> </ui:composition>
</h:body>
Try to include ui:repeat inside a4j:region, if it doesn't work then use a4j:repeat

Resources