primefaces tabView different tab content with dynamic tabs - primefaces

I have a problem with tabView. The 1st tab should always display the same content (called search template which is identified with #{not curSearch.isClosable()}. All other tabs are search instances (identified with #{curSearch.isClosable()}
Here is the code:
<p:tabView id="searchTabViewId" var="curSearch" value="#{searchBL.searchInstances}"
activeIndex="#{searchBL.activeTabIndex}" styleClass="searchTabView">
<!-- search template tab -->
<ui:include src="/icarchive/sections/search/firstSearchTab.xhtml">
<ui:param name="curSearch" value="#{curSearch}" />
</ui:include>
<!-- search instances tabs -->
<ui:include src="/icarchive/sections/search/searchInstanceTab.xhtml">
<ui:param name="curSearch" value="#{curSearch}" />
</ui:include>
</p:tabView>
Unfortunately there are methods on the 1st tabs curSearch object called which are used on 2nd and following tabs only. If I do not use the ui:insert it does not change anything.
Anybody knows where is my fault?
Regards
Oliver

This works:
<p:tabView id="searchTabViewId" styleClass="searchTabView" activeIndex="#{searchBL.activeTabIndex}">
<!-- do the iteration over the search instances NOT in the tabView because this will not work with ui:include -->
<c:forEach items="#{searchBL.searchInstances}" var="curSearch">
<p:tab closable="#{curSearch.isCloseable()}">
<f:facet name="title">
<p:graphicImage library="images" name="search_tab.png" height="16" styleClass="tabImage"
rendered="#{not curSearch.isCloseable()}" />
<h:outputText value="#{curSearch.title}" />
</f:facet>
<!-- do not use 2 ui:includes here, the dynamic must be in the src attribute to get it work -->
<ui:include
src="#{curSearch.closeable ? '/sections/search/searchInstanceTab.xhtml' : '/sections/search/firstSearchTab.xhtml'}">
<ui:param name="curSearch" value="#{curSearch}" />
</ui:include>
</p:tab>
</c:forEach>

I had the same problem, only solution i found is wrap include in other component and clamp with render which one is displayed. For initial load if you have ids depending on content you will need to set id prefix so that it does not allow empty id fields:
<p:tabView id="tabsView" dynamic="true" cache="true"
value="#{TabViewController.tabView.openedTabs}" var="tabDefinition" activeIndex="#{TabViewController.tabView.activeIndex}">
<p:ajax event="tabClose" listener="#{TabViewController.onCloseTab}" update="tabsView"/>
<p:ajax event="tabChange" update="tabsView"/>
<p:tab id="tab#{tabDefinition.id}" title="#{tabDefinition.title}" closable="true" action="">
<f:facet name="title">
<h:outputText value="#{tabDefinition.title}"/>
</f:facet>
<p:outputPanel style="display:block" rendered="#{'dataTable'.equals(tabDefinition.type)}">
<ui:include src="dataTable.xhtml">
<ui:param name="dataTableName" value="#{tabDefinition.contentName}"/>
</ui:include>
</p:outputPanel>
<p:outputPanel style="display:block" rendered="#{'form'.equals(tabDefinition.type)}">
<ui:include src="form.xhtml">
<ui:param name="formId" value="#{tabDefinition.id}"/>
<ui:param name="formName" value="#{tabDefinition.contentName}"/>
</ui:include>
</p:outputPanel>
</p:tab>
</p:tabView>

Related

Primefaces: Update not working for two components in different tabs

I have two selectBooleanCheckbox in differet tabs that are linked to the same variable in the backend bean, like this:
.xhtml:
<p:tabView id="tabsView" widgetVar="tabPanelWidget" dynamic="true" cache="true">
....
<p:tab id="tab1">
<p:outputPanel id="panel1">
<p:fieldset toggleable="false">
<p:panelGrid id="panelGrid1">
<p:row>
<p:column>
<p:outputLabel for="toggle1"/>
<p:selectBooleanCheckbox id="toggle1" value="#{backingBean.toogleBool}">
<p:ajax update="#(.toggle2)"/>
</p:selectBooleanCheckbox>
<p:column>
</p:row>
</p:panelGrid>
</p:fieldset>
</p:outputPanel>
</p:tab>
....
<p:tab id="tab2">
<p:outputPanel id="panel2">
<p:fieldset toggleable="false">
<p:panelGrid id="panelGrid2">
<p:row>
<p:column>
<p:outputLabel for="toggle2"/>
<p:selectBooleanCheckbox id="toggle2" value="#{backingBean.toogleBool}">
<p:ajax update="#(.toggle1)"/>
</p:selectBooleanCheckbox>
<p:column>
</p:row>
</p:panelGrid>
</p:fieldset>
</p:outputPanel>
</p:tab>
</p:tabView>
backingBean.java :
....
#Getter #Setter private boolean toggleMailAnhangExtrahieren = true;
....
Obviously this isn't my whole code as that would be too much to post here but I hope I included everything relevant. As you can see I try to use ajax to update the other selectBooleanCheckbox when one of them is clicked. As they are bound to the same variable, I would expect both selectBooleanCheckboxes to have the same status (both checked or both unchecked), but the other checkbox does not update. What am I doing wrong?
You need to fix the update part in the p:ajax tags:
#(.<class>) is a class-selector (Primefaces is using the jQuery Selector API, see https://api.jquery.com/category/selectors/), but you want to reference an id. So just use the id itself in the p:ajax tag, e.g.
<p:ajax update="toggle2"/>
Try using the tab id like this:
<p:ajax update="#form:tabsView:toggle2"/>

PrimeFaces' rowEditor doesn't work other than first try

I have a p:dataTable looks like this.
<p:remoteCommand name="rowEdit" action="#{servicesController.onRowEditCommand}" update="servicesTable" />
<p:remoteCommand name="rowEditCancel" action="#{servicesController.onRowEditCancelCommand}" update="servicesTable" />
<p:dataTable id="servicesTable"
value="#{servicesController.services}" var="service" rowKey="#{service.id}"
editable="true" editMode="row">
<p:ajax event="rowEdit" listener="#{servicesController.onRowEdit}"
oncomplete="rowEditCommand()"/>
<p:ajax event="rowEditCancel" listener="#{servicesController.onRowEditCancel}"
oncomplete="rowEditCancelCommand()"/>
<p:ajax event="rowSelect" update=":mainMenu"
listener="#{servicesController.sessionScopeServiceChanged}"/>
<!-- other columns here -->
<p:column style="width: 44px;">
<p:rowEditor/>
</p:column>
<!-- other columns here -->
</p:dataTable>
The p:rowEditor works fine for the first time. And it doesn't work from the second time. It gets to edit mode but the checkbox and x doesn't respond.
Two command names were wrong.
<p:remoteCommand name="rowEdit" ... />
<p:remoteCommand name="rowEditCancel" ... />
<p:ajax ... oncomplete="rowEditCommand()"/>
<p:ajax ... oncomplete="rowEditCancelCommand()"/>
I changed to.
<p:remoteCommand name="rowEditCommand" ... />
<p:remoteCommand name="rowEditCancelCommand" ... />
<p:ajax ... oncomplete="rowEditCommand()"/>
<p:ajax ... oncomplete="rowEditCancelCommand()"/>

BlockUI is not triggered when trigger is in a p:column

I am using buttons in a p:datatable and they are triggering a p:blockUI (PF 6.0)
When located in the footer of my datatable, the button does trigger the blockUI. When moved into a column, it does not trigger it
BlockUI
<p:blockUI block="blockPanel"
trigger="myForm:myTable:myButton myForm:myTable:myButton2">
Loading..<br />
<p:graphicImage name="images/loading_blue.svg" />
</p:blockUI>
Datatable
<p:panel id="blockPanel">
<h:form id="myForm">
<h:panelGrid columns="1" cellpadding="5">
<p:dataTable id="myTable" value="#{modelBean.myList}" var="entry">
<!-- Some data -->
<p:column headerText="Name">
<h:outputText value="#{entry.name}" />
</p:column>
<!-- Does not work -->
<p:column style="text-align: center">
<p:commandButton id="myButton" actionListener="#{bean.method()}" />
</p:column>
<!-- Works -->
<f:facet name="footer">
<p:commandButton id="myButton2" actionListener="#{bean.method()}" />
</f:facet>
</p:dataTable>
</h:panelGrid>
</h:form>
</p:panel>
Why ?
The following workaround did not work for me:
<p:commandLink ... onclick="bui.show()" oncomplete="bui.hide()">
...
<p:blockUI widgetVar="bui" />
As a workaround, I used pe:blockUI:
http://www.primefaces.org/showcase-ext/sections/blockui/blockPage.jsf
What I mean : You don't have any value in your datatable. Put it one, you can create a backingBean return one value and add property value=#{myBean.value}. Also you have data on you datatable ! Test it

trigger blockui from link within datagrid

I have the below datagrid which displays a list of student names as link.
<h:form id="gsform">
<p:dataGrid var="stuvar" rendered="#{gradeSheetController.listStudent != null}"
value="#{gradeSheetController.listStudent}" columns="5" layout="grid">
<p:commandLink actionListener="#{gradeSheetController.readStudentGradeSheet}"
update=":gsform:gscont, :gsform:buttoncont">
<h:outputText id="stname" style="font-size:16px" value="#{stuvar.studentFirstName}" />
<f:param name="selstudent" value="#{stuvar.studentSeq}" />
</p:commandLink>
</p:dataGrid>
I also have the below blockUI to freeze the screen until backend processing is done, currently used for a Save button.
<p:blockUI block=":entirePageBody" trigger="savebutton">
<h:panelGrid id="blockContent" columns="2">
<h:graphicImage library="images" name="loading.gif" style="margin-right:12px; vertical-align:middle;" />
<h:outputText value="Please wait, data is being processed..." style="white-space:nowrap;" />
</h:panelGrid>
</p:blockUI>
Now, I would also like to trigger the blockUI when the Student name link is clicked. Obviously, since the number of students will be dynamic and being within the datagrid, the code generated includes other aspects to the id like id="gsform:j_idt168:1:stname", id="gsform:j_idt168:2:stname" and so on.
Have no clue how to trigger the blockUI on click of the Student name link within the datagrid, please suggest.
Triggering/Hiding the blockUI from within dataGrid using onclick/oncomplete
<p:dataGrid var="stuvar" rendered="#{gsExamController.listStudent != null}"
value="#{gsExamController.listStudent}" columns="5" layout="grid">
<p:commandLink actionListener="#{gsExamController.readStudentGradeSheet}"
onclick="PF('bui').show()"
oncomplete="PF('bui').hide()"
update=":gsform:gscont, :gsform:remarkcont, :gsform:buttoncont">
<h:outputText style="font-size:16px" value="#{stuvar.studentFirstName}" />
<f:param name="selstudent" value="#{stuvar.studentSeq}" />
</p:commandLink>
</p:dataGrid>
<p:blockUI block=":entirePageBody" trigger="savebutton" widgetVar="bui">
<h:panelGrid id="blockContent" columns="2">
<h:graphicImage library="images" name="loading.gif" style="margin-right:12px; vertical-align:middle;" />
<h:outputText value="Please wait, data is being processed..." style="white-space:nowrap;" />
</h:panelGrid>
</p:blockUI>
A simple solution to your problem is to use Primefaces' selectors.
For example:
<p:commandLink value="Click me." styleClass="blockMeWhenClicked" />
<p:blockUI block=":ElementToBeBlocked" trigger="#(.blockMeWhenClicked)" />

Render same panel at multiple occasions

I am working with PrimeFaces and I want to know it rendering a panel multiple time within a same page is possible. For example, I have a panel like below:
<p:panel id="studentInfo">
<p:commandButton id="viewFullProfile" ....
<h:outputText value="Search" />
<p:inputText id="search" ....
</p:panel>
I want this panel to in each tab of a p:tabView control.
<p:tabView id="studentProfile">
<p:tab id="tabA">
..render "studentInfo" here...
</p:tab>
<p:tab id="tabB">
..render "studentInfo" here...
</p:tab>
<p:tab id="tabC">
..render "studentInfo" here...
</p:tab>
</p:tabView>
You will need one simple view like this :
studentInfo.xhtml
<ui:composition>
<p:panel>
#{item}
</p:panel>
</ui:composition>
Note : I'm currently passing #{item} as a parameter that could be a student entity for example.
Your view :
<p:tabView id="studentProfile">
<p:tab id="tabA">
<ui:composition template="studentInfo.xhtml">
<ui:param name="item" value="Student A" />
</ui:composition>
</p:tab>
<p:tab id="tabB">
<ui:composition template="studentInfo.xhtml">
<ui:param name="item" value="Student A" />
</ui:composition>
</p:tab>
<p:tab id="tabC">
<ui:composition template="studentInfo.xhtml">
<ui:param name="item" value="Student A" />
</ui:composition>
</p:tab>
</p:tabView>