PrimeFaces - Relationship between <p:rowExpansion> and <p:rowToggler>? - jsf

I'm using Primefaces 4.0. I'm starting to get a feel for this, but can't seem to get it straight, and the documentation hasn't helped much with this specific question.
Can someone explain the relationship between these two components? Does <p:rowExpansion> dictate what is displayed when <p:rowToggler> is used?

Don't know what confuses you, but inside <p:rowExpansion> you put the content which will be displayed when <p:rowToggler> is clicked. You've probably seen examples, but I'll put one here just for reference (taken from primefaces showcase)
<p:dataTable var="car" value="#{dtBasicView.cars}">
<f:facet name="header">
Expand rows to see detailed information
</f:facet>
<p:column style="width:16px">
<p:rowToggler />
</p:column>
<p:column headerText="Id">
...
</p:column>
<p:rowExpansion>
<p:panelGrid columns="2" columnClasses="label,value" style="width:300px">
<f:facet name="header">
<p:graphicImage name="demo/images/car/#{car.brand}-big.gif"/>
</f:facet>
<h:outputText value="Id:" />
<h:outputText value="#{car.id}" />
...
</p:panelGrid>
</p:rowExpansion>
</p:dataTable>

Related

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".

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.

How to update a dynamically generated datatable without touching the rest of the page?

I have a setup in a view, where I display datatables dynamically. That is happening inside a p:accordion-Element, which is generating the tabs dynamically (and therefore the datatables inside).
The user now has the possibility (well, should have..) to add, edit and remove objects to the datatable and therefore to the object that is represented by the tab.
The add- and edit-functions work via dialogs. After successful adding or editing I want to update the datatable containing the data.
If I update the whole accordion-panel I lose the focus on the current tab which is really bad for the user-experience, especially because the other sub-pages of the project always only update the datatable.
After some googling I found out that I can't generate the IDs of JSF-components dynamically, what would make the whole thing a process of minutes.
I also do not have any index I could use to "cheat" and save in my backing-bean when I open the dialog.
I also found out that I could work-around this issue by using JSTL but this is prohibited due to a limited set of allowed languages.
The current setup looks like this:
<p:accordionPanel id="academicYearAccordionPanel"
value="#{academicYearAndClassController.academicYears}"
var="academicYear" multiple="true" dynamic="true" activeIndex="-1"
style="width:100%;">
<p:tab id="academicYear-#{academicYear.academicYear}" title="Jahrgang - #{academicYear.academicYear}">
<p:outputPanel style="float:right">
<p:commandButton value="Löschen" icon="ui-icon-close"
actionListener="#{academicYearAndClassController.setAcademicYear(academicYear)}"
process="#this"
oncomplete="PF('wConfirmAcademicYearDelete').show();">
</p:commandButton>
</p:outputPanel>
<p:spacer style="height:50px;" />
<p:separator />
<!-- Tabcontent -->
<p:outputPanel>
<p:outputPanel style="float:right">
<p:commandButton value="Hinzufügen" icon="ui-icon-plusthick"
actionListener="#{academicYearAndClassController.setAcademicYear(academicYear)}"
process="#this"
oncomplete="PF('wAddSchoolclassDialog').show();">
</p:commandButton>
</p:outputPanel>
<h:panelGrid columns="2">
<h:outputText
value="Klassen des #{academicYear.academicYear}. Jahrgangs" />
<p:spacer style="height:50px;" />
</h:panelGrid>
<p:dataTable emptyMessage="Keine Klassen vorhanden"
id="schoolclassTable"
var="schoolclass"
selection="#{academicYearAndClassController.schoolclass}"
value="#{academicYearAndClassController.getSchoolclasses(academicYear)}"
selectionMode="single" rowKey="#{schoolclass.name}"
scrollable="true" scrollHeight="500">
<p:column headerText="Name">
<h:outputText value="#{schoolclass.identifier}" />
</p:column>
<p:column headerText="Klassenlehrkraft">
<h:outputText
value="#{schoolclass.teacher.name} (#{schoolclass.teacher.symbol})" />
</p:column>
<p:column headerText="Klassenraum">
<h:outputText
value="#{schoolclass.room.name} (#{schoolclass.room.locationName})" />
</p:column>
</p:dataTable>
</p:outputPanel>
</p:tab>
</p:accordionPanel>
I want to update the element with the ID schoolclassTable. How can I achieve this?

p:cellEditor does not save textarea onblur when clicking a link

Saving a text inside a p:cellEditor > p:inputTextarea works perfectly onblur when clicking outside the cell.
However when clicking on a link (e.g. commandButton, commandLink) coming from a p:cellEditor > p:inputTextarea it does not execute the p:ajax cellEdit event beforehand. It instead executes the clicked link.
This is not correct since it works for p:inputTextarea without a p:cellEditor. I realize this might as well be a Primefaces bug. Any idea how to work around this?
<p:dataTable>
<p:ajax event="cellEdit" listener="#{bean.onCellEdit}" />
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{model.text}" />
</f:facet>
<f:facet name="input">
<p:inputTextarea value="#{model.text}" />
</f:facet>
</p:cellEditor>
<p:dataTable>
<p:commandButton actionListener="#{bean.someOtherAction}" />
I submitted the bug to Primefaces. But is there a workaround for this via javascript/jQuery?
After no success on the Primefaces bug report I ended up hooking up the listener to all of the p:cellEditor instances directly. It seems to work and I'm not losing inputs anymore.
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{model.text}" />
</f:facet>
<f:facet name="input">
<p:inputTextarea value="#{model.text}">
<!-- this is the relevant line -->
<p:ajax listener="#{bean.onCellEdit}" global="false" update="#this" />
<!-- end relevant line -->
</p:inputTextarea>
</f:facet>
</p:cellEditor>
I did quite similar but without <p:cellEditor>. In that mode that did not work for me.
But if you use just
<p:column>
<p:selectBooleanCheckbox value="#{listElement.field1}">
<p:ajax listener="#{bean.saveAction}" global="false" update="#this"/>
</p:selectBooleanCheckbox>
</p:column>
<p:column>
<p:inputTextarea value="#{listElement.field2}">
<p:ajax listener="#{bean.saveAction}" global="false" update="#this"/>
</p:inputTextarea>
</p:column>
</p:dataTable>

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