I have a "normal" paging with a dataTable. The first "load" brings in 25 items from the database.
In the ajax "page" event I am bringing the following elements in blocks of 25 items. Everything works perfectly with version 5.1 of Primefaces, but in version 5.2 the onPageChange method is not called, in fact paging does nothing.
If in the ajax event "page" I add process="#this" it does call the bean, but not the specified onPageChange method but a start method marked with the #PostConstruct annotation (in this way the same first 25 items and pagination always shows these items).
<p:panel id="..."
header="..."
style="..."
toggleable="true"
toggleSpeed="200" >
<p:dataTable var="some_var"
id="myDataTable"
widgetVar="pag"
first="#{[bean].first}" <-- bean attribute
value="#{[bean].collectionOfObjects}" <-- loading of the first 25 elements
rows="20"
paginator="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
emptyMessage="..."
lazy="true"
rowIndexVar="rowIndex"
rowStyleClass="#{(rowIndex mod 2) eq 0? '...' : '...'}">
<p:ajax event="page"
listener="#{[bean].onPageChange}"/> <-- load the next 25 items (successively)
<p:ajax event="sort"
listener="#{[bean].orderListing}"/>
<p:column width="..."
headerText="..."
style="..."
sortBy="#{some_var.id}"
id="...">
...
</p:column>
[rest of columns]
</p:dataTable>
</p:panel>
Back (just as an outline):
#PostConstruct
protected void init() {
...
this.collectionOfObjects = new GenericLazyModel<CollectionOfObjects>(...);
}
//Method not called by ajax.
public void onPageChange(PageEvent event) {
//Next 25 items
this.collectionOfObjects = new GenericLazyModel<CollectionOfObjects>(...);
}
Versions: primefaces 5.2, jsf-api 2.2.2, jsf-impl 2.2.2 (updating these last two will be very expensive).
In this post there are several possibilities, but I have not managed to solve the error after reading everything carefully.
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated
Thank you very much to all!
Finally, after several tests, I have updated the version of PF to 5.3 and it has worked. The error when updating to this version 5.3 was not from the application itself, it was from the primefaces-extensions library that had to be updated to v4.0.0 (at least). If anyone has a problem updating the PF library, check the version of primefaces-extensions as well.
Related
I am using a PrimeFace5.0 DataTable. I want to add the ajax rowSelect event to it. However, when a row is clicked, the event is not fired. My table and Ajax are declared like so:
<p:dataTable id="leTable"
value="#{leList.leItems}"
var="leItem"
rowKey="#{leItem.id}"
scrollable="true"
scrollHeight="100%"
selection="#{leList.selectedLEs}"
selectionMode="multiple"
rowIndexVar="rowIndex"
resizableColumns="true"
liveResize="true"
>
<p:ajax event="rowSelect"
listener="#{leAction.onLeRowSelect}"
update=":form:rowIndexId"
onstart="getLeRowIndexId(event)">
</p:ajax>
....
</p:dataTable>
Action-Bean:
public void onLeRowSelect(SelectEvent event)
{
....
}
The whole thing worked well with the Prime Faces 4.0. But after switching to version 5.0 it no longer works. Can someone please help me?
I have a problem with a form not triggering its commandButton action method.
When I submit the form without prior update (not selecting any node in the tree), the method triggers just fine.
As soon as the form is Ajax-updated, the commandButton won't call its action anymore.
Here is the JSF code:
<p:layoutUnit position="center">
<p:tree orientation="horizontal" value="#{flightTypeController.tree}" var="node"
selectionMode="single" selection="#{flightTypeController.selectedNode}">
<p:ajax event="select" listener="#{flightTypeController.onNodeSelect}" update=":typesTree"/>
<p:treeNode>
<h:outputText value="#{node.name}"/>
</p:treeNode>
</p:tree>
<h:form id="typesTree">
<p:inputText disabled="true" id="outputParent" value="#{flightTypeController.selectedOne.name}"/>
<p:inputText id="outputName" value="#{flightTypeController.current.name}"/>
<p:commandButton ajax="false" icon="ui-icon-disk" value="#{bundle.general_create}" action="#{flightTypeController.create()}"/>
</h:form>
</p:layoutUnit>
And the java listener:
public void onNodeSelect(final NodeSelectEvent event) {
final Object res = event.getTreeNode().getData();
if (res instanceof FlightType) {
selectedOne = (FlightType) res;
} else {
selectedOne = null;
}
}
I already check BalusC's bible and JS Fix but without success.
I've seen similar behaviours quite often (and had to find workarounds) so I might have misunderstood something fundamental.
Oh, yes, I checked multiple times : no nested forms in my code.
The JS fix which you found is hooking on jsf.ajax.addOnEvent which is only triggered by <f:ajax>, not by PrimeFaces components which use jQuery under the covers.
To cover PrimeFaces ajax requests as well, grab the current version of the JS fix (I have recently updated that post) and add the following to apply this fix on jQuery ajax requests as well:
$(document).ajaxComplete(function(event, xhr, options) {
if (typeof xhr.responseXML != 'undefined') { // It's undefined when plain $.ajax(), $.get(), etc is used instead of PrimeFaces ajax.
fixViewState(xhr.responseXML);
}
}
Disclaimer: I haven't tried your specific use case. But, theoretically, it should solve your problem.
We are using Primefaces 3.0.RC2 in our application with seam faces and CDI. We have followed the lazy loaded data table implementation on the component showcase. Since we have a large dataset, we have overridden the load() method to fetch only pagewise results. (vs loading all records in memory at once).
The pagination works as expected, however the sorting does not. The records get sorted correctly the first time the column header is clicked. For all subsequent clicks, the load() method is called twice, sending different values for the sorting order as a result of which, the sort order remains the same on the table. It seems like both the load() calls are being made in the APPLY_REQUEST_VALUES phase.
Can anyone provide any inputs as to why this is happening and how it can be avoided. Any pointers would be highly appreciated.
Some additional info:
As stated earlier, we have overriden the load() method and have it actually query the DB to fetch sorted results pagewise (by specifying max results and order by in the query) and it works fine.
#Override
public List<ABC> load(int first, int pageSize, String sortField, SortOrder
sortOrder, Map<String, String> filters)
{
// Fetch data pagewise from the database
datasource = dao.findPagewiseSortedResults(sortField,
SortOrder.ASCENDING == sortOrder ? true : false, first, pageSize);
// Set the row count
this.setRowCount((int) dao.findTotalCount());
return datasource;
}
However, on clicking the column on the datamodel for sorting, 2 post requests are made.
Find below the xhtml code:
<p:dataTable id="dataTable" var="record"
value="#{testBean.lazyModel}" paginator="true" rows="5"
paginatorTemplate="{FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
selectionMode="single" selection="#{testBean.selectedRecord}"
sortBy="#{record.username}">
<p:ajax event="rowSelect" listener="#{testBean.onRowSelect}"
update=":form:display" oncomplete="accountDialog.show()" />
<p:ajax event="colResize" update=":form:growl"
listener="#{testBean.onResize}" />
<p:column sortBy="#{record.username}"
filterBy="#{record.username}">
<f:facet name="header">
<h:outputText value="User Name" />
</f:facet>
<h:outputText value="#{record.username}" />
</p:column>.........
</dataTable>
We have even upgraded to the latest Primefaces version (3.0.1) but it hasn't helped. Are we missing anything? Any pointers would be very helpful.
Thanks.
Since you are providing the sorting by use of the load() method, you don't have to use dataTable's native sorting tool. You need to remove the sortBy attribute from p:dataTable tag.
The component should be defined this way:
<p:dataTable id="dataTable" var="record"
value="#{testBean.lazyModel}" paginator="true" rows="5"
paginatorTemplate="{FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
selectionMode="single" selection="#{testBean.selectedRecord}" >
EDIT
This way, you'll have your column sortable exactly in the order specified by the client: you will read the SortOrder specified, with the Java code you have posted, and you will use that SortOrder consequently in your implementation of dao#findPagewiseSortedResults()
I am using the LazyDataModel to populate a a table with 33 items(A sub set of a long list of parts and can grow or shrink) in pages of 10. the table deceleration is as follows
<p:dataTable var="spare" value="#{sitePartController.selectParts}" paginator="true" lazy="true"
currentPageReportTemplate="(Entries: {startRecord} - {endRecord} of {totalRecords}, Page: {currentPage}/{totalPages})"
paginatorTemplate="{CurrentPageReport}{FirstPageLink}{PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink}"
rows="10" selection="#{sitePartController.selectedParts}"
paginatorAlwaysVisible="false"
dynamic="true"
>
The pagination works fine filling the currentPageTemplate with 33 items 4 pages 1- 10 etc. When i press a link all the pagination output changes correctly(page 2/4 etc). However the data in the table does not change, just continues to show records 0-9. My override Load method is as follows.
selectParts = new LazyDataModel() {
#Override
public List<SitePart> load(int first, int pageSize, String string, boolean bln, Map map) {
return getSiteSpares(first,first+pageSize);
}
};
int totalRowCount = getSparesCount();
selectParts.setRowCount(totalRowCount);
When I stop my debug in the load method no matter which datatable pagination link I select; first is always 0 and page is 10 (as expected). How do I get the datatable to send the correct first index or have I missed something fundamental in the last 6 hours of googleing and trying various alternatives.
Not sure if it could cause the issue, but shouldn't it be:
selectParts = new LazyDataModel<SitePart>(){
Try to put p:dataTable inside h:form
<h:form id="form">
<p:dataTable>
</p:dataTable>
</h:form>
Good Afternoon,
I have a search page that uses ajax to render a several datatables without refreshing the page.
It is mandatory for me to call a Method as a Listener for each table.
Below is the snippet for the first datatable that works fine.
To render a second datatable I need to call a method #{evalController.prepareList} as a Listener for the ajax. The problem is that <f:ajax "Listener" attribute won't take more than one method.
So the remaining way is to call <f:ajax several times, and each time with a different listener, which does not work. Is there a way to achieve this?
If not, should I create a method in the managed Bean that calls all the methods that I need and use it as the one listener?
Thanks in advance for your help.
<h:form id="searchform">
<h:panelGrid columns="3" >
<p:inputText value="#{ddnController.patientID}" id="pidinput" maxlength="7" size="7">
<f:ajax execute="#this" event="keyup" render="searchbutton ddntable" listener="#{ddnController.prepareList}"/>
</p:inputText>
<h:commandButton image="#{resource['images/search.png']}" id="searchbutton" value="#{bundle.Search}"
action="submit" actionListener="#{ddnController.prepareList}"
disabled="#{empty ddnController.patientID or ddnController.patientID.equals('0')}"/>
<p:panel><h:outputText value="Saisir 0 pour avoir tous les Patients" style="font-style: italic;"/></p:panel>
</h:panelGrid>
<p:dataTable id="ddntable" value="#{ddnController.items}" var="ddn" rendered="#{!empty ddnController.items}" paginator="true" >....
I am still not sure why the composite method do not have effect when called. Probably it is not called during before or after the right phase (I'll be profiling it later). Anyway, I found a solution with two edges (it is solving my problem but makes me sacrifice the use of ajax) :
So Instead of calling - from each managed bean - the method (prepareList()) which I use as listener:
private DataModel items = null; // Getter to retrieve items
// ......
public String prepareList() {
recreatemodel();
return "List";
}
private void recreatemodel(){
items=null;
}
(by the way, this method sets the datamodel to NULL to refresh it, and that is how my datatables get refreshed).
Inside the command button I nested property action listener:
<h:commandButton image="#{resource['images/search.png']}" id="searchbutton" value="#{bundle.Search}"
action="submit"
disabled="#{empty ddnController.patientID or ddnController.patientID.equals('0')}">
<f:PropertyActionListener target="#{ddnController.items}" value="#{null}" />
<f:PropertyActionListener target="#{evalController.items}" value="#{null}" />
<f:PropertyActionListener target="#{corController.items}" value="#{null}" />
<!--...etc -->
</h:commandButton>
I wish <f:PropertyActionListener /> could be nested inside <h:ajax/>.
If somebody has a solution that allows to use property action listener and ajax to avoid submitting the form with a button, s/he is welcome. I'll make then his/her answer as accepted.