Update p:datatable and retain the rowexpansion status - jsf

I have datatable with rowexpansion that have another datatable inside it.
The structure like below:
<p:dataTable id="machine-table" value=#{machinePage.machines} var="machine" styleClass="machine-table">
<p:column style="width:16px">
<p:rowToggler rendered="#{machine.projectsInMachine.size() > 0}" />
</p:column>
some other machine column here...
<p:rowExpansion >
<p:dataTable value="#{machine.projectsInMachine}" var="project" styleClass="project-subtable" >
some project column here
</p:dataTable>
</p:rowExpansion>
Then I have a pull that will retrieve the machines and the projects data every couple minute, Is there any way that I can update it and retain the current expansion status? Because currently it will always close all the expansion (I update the entire table using poll below).
<p:poll widgetVar="machinesPoll"
interval="60" listener="#{machinePage.prepare()}"
async="true" global="false"
autoStart="true" process="#this"
update="machine-table" partialSubmit="true"
ignoreAutoUpdate="true" />
I can't find any reference regarding the expansion status that I can save in bean. I use: primefaces 6.0 , JSF 2.2.13

Related

<rowExpansion> evaluated during JSF phases

I have a datatable using rowExpansion.
When the page is loaded, the rowExpansion is not evaluated, which is fine.
When the paginator is used to show the next results or if a submission is done - the rowExpansion evaluation is triggered.
Here is a XHTML example :
<h:form>
<p:dataTable var="data" value="#{bean.dataList}" paginator="true">
<p:column headerText="Details">
<p:rowToggler />
</p:column>
<p:rowExpansion>
<h:panelGroup rendered="#{not empty data.detail}">
<ui:include src="dataDetail.xhtml" />
</h:panelGroup>
</p:rowExpansion>
</p:dataTable>
<h:commandLink id="addData" value="Add data" action="#{bean.addData}" />
</h:form>
I've profiled this flow using visualVM, and used the debugger, to discover that the data.getDetail() method was called during the following JSF phases : (ApplyRequestValuesPhase, ProcessValidationsPhase, UpdateModelValuesPhase), when the paginator was used.
I've come to the deduction that the rowExpansion is part of the view, and is evaluated as a normal component.
Would you mind telling me if it is the expected behaviour for rowExpansion ?
Is there a correct way to prevent the evaluation of the rowExpansion content when using the paginator ?
Thanks for your answers.
NB : I'm using PrimeFaces 5.2.

Dynamically adding components in multiple columns & legend creation [duplicate]

I'm working on dashboard application where I have to retrieve a set of records and display in dynamic tables boxes. Page frame length is fixed. now of columns and rows can be initialized. It should look like this sample:
Currently I'm using data table to display but it prints all the data in one column. How would I change my code to above pattern?
<o:dataTable id="tabBlSearch" var="item"
onkeyup="handleLeftRightArrowOnDataTable('frmDashBoard:tabBlSearch')"
value="#{bLDashBoardAction.listBondLoc}">
<o:column style="width: 20px;">
<h:outputText value="#{item.awb}" />
</o:column>
</o:dataTable>
You can achieve this with standard JSF components using a <h:panelGrid> wherein <c:forEach> is been used to generate the cells during the view build time. The <ui:repeat> won't work as that runs during view render time.
<h:panelGrid columns="5">
<c:forEach items="#{bean.items}" var="item">
<h:panelGroup>
<h:outputText value="#{item.value}" />
</h:panelGroup>
</c:forEach>
</h:panelGrid>
As to component libraries, I don't see anything in OpenFaces' showcase, but PrimeFaces has a <p:dataGrid> for exactly this purpose, even with pagination support.
<p:dataGrid columns="5" value="#{bean.items}" var="item">
<p:column>
<h:outputText value="#{item.value}" />
</p:column>
</p:dataGrid>

p:rowExpansion gets rendered even though it's not toggled

I have a problem with data in a <p:rowExpansion> being loaded before the row is expanded (which leads to loads of web service requests).
I am using PrimeFaces 5.2. I have a dataTable with lazy loading and pagination. Inside of the table, I have <p:rowToggler> with a <p:rowExpansion>:
<p:dataTable var="order"
widgetVar="orderTable"
lazy="true"
value="#{ordersBean.orders}"
paginator="true"
rows="20"
rowsPerPageTemplate="20,50,100"
filterDelay="300"
styleClass="filtered">
<p:column width="4%">
<p:rowToggler />
</p:column>
<p:column headerText="Order number" width="96%">
<h:outputText value="#{order.number}" />
</p:column>
<p:rowExpansion>
<h:panelGrid columns="1">
<h:outputText value="#{order.number}" />
<h:outputText value="#{order.info}" />
<h:dataTable var="item" value="#{ordersBean.getItemsInOrder(order.number)}">
<h:column>
<h:outputText value=" #{item.title}" />
</h:column>
</h:dataTable>
</h:panelGrid>
</p:rowExpansion>
</p:dataTable>
When I first load the page, the getItemsInOrder() method is not called, except for when I expand a row. But if I navigate to page 2 (or if I navigate back to page 1 later) using the paginator, then getItemsInOrder() is called for every row in the outer table. Since I have 20 rows showing, navigating between the pages leads to 20 web service requests (in getItemsInOrder()).
How do I prevent it from calling the getItemsInOrder() method until the row is expanded?
I have the same problem. Until I find a better solution, this is the workaround I am using:
register a (DataTable event-) listener on event rowToggle.
In the listener, store an identifier of the toggled row. Hint: you can get the row object with event.getData()
Instead of directly accessing the data requesting component, write a proxy method in front of it which checks if the requested object belongs to the identifier stored in the listener.

PrimeFaces DataExporter to XLS for multiple tables

Am trying to Export XLS format from multiple tables. I have browsed and used some code, But its not working. Using primefaces extensions code is there but complete code is not there it seems in this
link.
I need solution for this.
Code i have used :
Tbl1, Tbl2, Tbl3 are table widgetVar's.
<p:commandLink id="xls" ajax="false" >
<p:graphicImage value="/images/excel.png" />
<pe:exporter type="xlsx" target="Tbl1, Tbl2, Tbl3" fileName="tables"/>
</p:commandLink>
You should not address them by widgetVar. From the PrimeFaces Extensions Exporter (emphasis mine):
Here we can export multiple tables by providing multiple datatable server ids with the delimiter as "comma"(or ",").
I work with primefaces 6.2 and this works for me (I’m not sure about other versions) without use primefaces extension
<p:dataTable id="tbl1" value="#{ManagedBean.listValues}" var="vt">
<p:column headerText="LabelPrint">
<h:outputText value="#{vt.id}"/>
</p:column>
</p:dataTable>
<p:dataTable id="tbl2" value="#{ManagedBean.otherList}" var="vt2">
<p:column headerText="Name Field Print">
<h:outputText value="#{vt2.name}"/>
</p:column>
</p:dataTable>
<h:commandLink>
<p:graphicImage url="#{resource['/images/icons/table-xls.png']}"/>
<p:dataExporter type="xls" target="tbl1, tbl2" fileName="My Data" pageOnly="true" />
</h:commandLink>
You separate your "id" of tables for export with (,) in attribute target of p:dataexporter object.

How do update jsf datatable column only

I have a counter in a column of a datatable. Once the counter reaches a certain time, I need to change the background color of that column only. The data for the table is being pulled from a database. I'm using a4j:poll to reRender the column but the issue is that the entire table is rendered. Some code below:
<a4j:region>
<h:form>
<a4j:poll id="poll" interval="1000" enabled="true" reRender="blink" limitToList="true" />
</h:form>
</a4j:region>
<h:form id="form1">
<a4j:outputPanel id="panel1" ajaxRendered="true">
<h:dataTable id="blinks" styleClass="tableClass" value="#{bean.list}" var="_item">
<h:column id="blink">
<f:facet name="header">
<h:outputText value="Header1" />
</f:facet>
<div id="div1" class="#{bean.check() ? 'red' :''}">
<h:outputText value="Counter text (counts seconds)" />
</h:column>
</h:dataTable>
</a4j:outputPanel>
</h:form>
If you meet the following minimum req' JSF 2.0, EL 2.1 and Servlet 2.5
You can try out the Ajax#updateColumn() by Omnifaces , there is an example on how to use it in the showcase
Note that Ajax#updateRow() and Ajax#updateColumn() can only update
cell content when it has been wrapped in some container component with
a fixed ID.
Maybe you can use a push server side events to trigger the update on client side instead of use polling which performs full form.
http://livedemo.exadel.com/richfaces-demo/richfaces/push.jsf?tab=choices&cid=987178
A full description how to use this: Using RichFaces Push and DataTable Ajax Keys for Partial Tables Updates
you should re render by column id, but because you have data which coming from database, and it is a one list, can you confirm what you can do call which real can update one column?

Resources