Is there any way to update PrimeFaces data table without updating the table headers? - jsf

This is a clumsy question!!! :)
Can this be made possible somehow? Can <p:dataTable> (whatever lazily loaded or otherwise) be updated without updating its headers (The contents (rows) inside the table along with the footer should be updated without updating the table headers)?
Updating of <p:dataTable> may be triggered by any UICommand like <p:commandButton>, <p:commandLink> and alike.
Something like this can be visualized, when we edit/update rows using <p:cellEditor> in conjunction with <p:rowEditor/> in <p:dataTable> (not sure about single cell editing).
<p:dataTable id="dataTable" var="row" value="#{bean}" ...>
<p:column headerText="Header 1" sortBy="#{row.property1}" filterBy="#{row.property1}">
....
</p:column>
<p:column>
<!--They may be our own headers-->
<f:facet name="header">
Header 2
...
</f:facet>
....
</p:column>
...
</p:dataTable>

Easiest way is to use PrimeFaces Selectors (PFS) for this. This only requires the desired cell content being wrapped in another component with an ID and a style class — so that jQuery can find and collect them.
E.g.
<p:dataTable ...>
<p:column>
<f:facet name="header">...</f:facet>
<h:panelGroup id="col1" styleClass="cell">...</h:panelGroup>
</p:column>
<p:column>
<f:facet name="header">...</f:facet>
<h:panelGroup id="col2" styleClass="cell">...</h:panelGroup>
</p:column>
<p:column>
<f:facet name="header">...</f:facet>
<h:panelGroup id="col3" styleClass="cell">...</h:panelGroup>
</p:column>
...
</p:dataTable>
<p:commandButton value="update" update="#(.cell)" />
That wrapping is clumsy, yes, but that's best you can get without homebrewing a custom renderer. You can always create a <my:column> tagfile to reduce the boilerplate.
See also:
How do PrimeFaces Selectors as in update="#(.myClass)" work?

Related

p:pickList ignores attributes of <p:column>

I am currently developing an application where the user can use a picklist to make certain associations.
I would like to display the object's attributes in different columns inside the picklist, for example the object car would display its id, year and color. However, the headerText of the column is not working. The column only displays the data but PrimeFaces seems to ignore the attribute headerText among others like sortBy. Is there any workaround? What am I doing wrong? p:column seems to work fine on a DataTable but not on a PickList and I really need to use a PickList or at least something with very similar functionalities.
Below is my code:
<p:pickList id="pickListAssociacao" value="#{associacaoPickListView.carsPickListView}" var="car" itemLabel="#{car.brand}" itemValue="#{car}">
<p:column headerText="Header1">
<h:outputText value="#{car.brand}" />
</p:column>
<p:column headerText="Header2" sortBy="#{car.year}">
<h:outputText value="#{car.year}" />
</p:column>
<p:column headerText="Header3">
<h:outputText value="#{car.year}" />
</p:column>
</p:pickList>
Thanks for your time.

primefaces editable datable with autocomplete stuck up on edit or edit cancel [duplicate]

I am using JSF 2.2 with Primefaces 5.1. There is an editable primefaces datatable with pagination enabled.
<p:dataTable editMode="row"
editable="true"
value="#{usersBean.users}"
var="user" paginator="true" rows="20">
<p:ajax event="rowEditInit" onstart="handleRowEditInit(event,this);"/>
<p:column>
<p:rowEditor/>
</p:column>
<p:column headerText="Real name">
<p:cellEditor rendered="true">
<f:facet name="input">
<p:inputText value="#{user.realName}"/>
</f:facet>
<f:facet name="output">
<h:outputText value="#{user.realName}"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="User name">
<p:cellEditor>
<f:facet name="input">
<p:inputText value="#{user.userName}"/>
</f:facet>
<f:facet name="output">
<h:outputText value="#{user.userName}"/>
</f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
Every time the page is changed the datatable does an AJAX POST with all the data of the current page. As you can partly see in the image below.
For big tables with much data this results in huge requests. This is not neccessary right? Is there a way to change this behavior?
Indeed, when you submit a form in HTML, by default every single HTML input element will be sent as request parameter. PrimeFaces ajax components therefore offer the partialSubmit="true" attribute which will then send only the HTML input elements covered by the process attribute, which defaults in <p:ajax> to #this and in <p:commandXxx> to #form.
So, just add this to the data table in case to optimize pagination performance:
<p:ajax event="page" partialSubmit="true" />
And add this to any command button which only needs to access the current row in the data table (e.g. to show it in a dialog) to optimize action processing performance:
<p:commandButton ... process="#this" partialSubmit="true" />
You can also configure it globally via below context param in web.xml:
<context-param>
<param-name>primefaces.SUBMIT</param-name>
<param-value>partial</param-value>
</context-param>
And then for cases where you actually need a full submit, explicitly use partialSubmit="false".

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.

How to use c:forEach with p:dataTable and p:columnGroup?

I want to use a special form of grouping 'dynamic' columns. This is however not supported as stated in my other question. Using c:forEach was suggested as a possible solution
Which is correct way to use c:forEach for defining table header and colums.
My code BEFORE:
<p:dataTable id="resultTable" var="result" value="#{myBean.searchResults}" scrollable="true">
<p:columns value="#{myBean.columns}" var="column" columnIndexVar="colIndex">
<f:facet name="header" >
<h:outputText value="#{column.header}"/>
</f:facet>
<h:outputText value="#{result[column.property]}"/>
</p:columns>
</p:dataTable>
and code AFTER transformation (didn't work - table is not displayed):
<p:dataTable id="resultTable" var="result" value="#{myBean.searchResults}" scrollable="true">
<p:columnGroup type="header">
<p:row>
<c:forEach items="#{myBean.columns}" var="column">
<p:column headerText="#{column.header}"/>
</c:forEach>
</p:row>
</p:columnGroup>
<c:forEach items="#{myBean.columns}" var="column" >
<p:column>
<h:outputText value="#{result[column.property]}"/>
</p:column>
</c:forEach>
</p:dataTable>
PrimeFaces version 3.4.1
The "by the book" way to create dynamic columns would be to use the "Dynamic Columns" feature of the data table.
Any way, I did something very similar to what you are trying to do in the past, using c:forEach. The only difference was that I was not using p:columnGroup at the same time.
So, code like
<p:dataTable id="resultTable" var="result" value="#{myBean.searchResults}" scrollable="true">
<c:forEach items="#{myBean.columns}" var="column" >
<p:column headerText="#{column.header}">
<h:outputText value="#{result[column.property]}"/>
</p:column>
</c:forEach>
</p:dataTable>
should really work. When you do this way, you add p:column objets in the component tree before the p:datatable analyze the tree. So, this does the trick.
Beware that this can lead to problems in edge, ajax cases. So, if you can, just stick to the built-in dynamic columns feature.

Primefaces: PanelGrid in Datatable LiveScroll

Is there anyone who tried that? When it loads more panelGrid, table just duplicates them.
this picture result of that simple code block. Upper side shows how should it be rendered in a proper way but it goes wrong like at the down side.
<p:dataTable liveScroll="true" value="#{PanelController.panelList2}" var="GridPanel" scrollable="true" scrollRows="20" scrollHeight="100" rows="5">
<p:column>
<p:panelGrid>
<p:row>
<p:column>
<h:outputText value="ehehe"></h:outputText>
</p:column>
</p:row>
</p:panelGrid>
</p:column>
</p:dataTable>
If it was up to me I'd use the p:dataScroller und then use the panelgrid inside that. Take a look at this: http://www.primefaces.org/showcase/ui/data/datascroller/inline.xhtml

Resources