-
1. Re: Displaying total rowCount of a dataTable
ilya_shaikovsky Jul 28, 2009 8:50 AM (in response to cmathrusse)How about just to retrieve it from model?
-
2. Re: Displaying total rowCount of a dataTable
cmathrusse Jul 28, 2009 9:16 AM (in response to cmathrusse)That would only work on the initial display of the table. When filtering is performed, based on filterBy, the model would not get updated with the matching row count.
-
3. Re: Displaying total rowCount of a dataTable
ilya_shaikovsky Jul 28, 2009 9:24 AM (in response to cmathrusse)so properly defined model could care about it. :)
http://livedemo.exadel.com/richfaces-demo/richfaces/dataTable.jsf?tab=modifiableDataModel&cid=2463605 -
4. Displaying total sums in the footer of a dataTable
kado Aug 20, 2010 7:45 AM (in response to ilya_shaikovsky)Hi,
sorry for dig up an old thread, but I've the same problem as Chris (had). We are using JEE 6 with JPA and Richfaces 3.3.3 and I don't know how to implement my own data model described in the example. And I also had no idea how to use the own data model to solve this problem.
I calculate the sums of some columns and give it out in the footer. But when I use a filter, the footer will not updated at this time and the sum is the same as before.
It would be very nice if someone can help me, because it is one of the main characteristics of the application.
Thanks in advance.
Greetings, Jan
-
5. Re: Displaying total sums in the footer of a dataTable
kado Aug 24, 2010 9:29 AM (in response to kado)I've rewritten the BaseModifiableHibernateDataModel from the example to a JPA compatible one, with JPA Criteria API. But I've another problems now:
Problem #1 - Performance: The performance is unacceptable, cause of the many database queries, which are triggered by walk() method. Can somebody tell me why the walk() and modify() method is called so often although the filter is typed once again?
Problem #2 - Call sequence: The first method which will be called by typing the filter, is walk(). After that modify() is called. When I tried to get the list of items in my DisplayBean, I can't be sure that walk() is called before I got the items. I probably get the items from an old query which doesn't represent my actual displayed data.
So, please try to explain how to solve my inital problem with an own data model?
-
6. Re: Displaying total sums in the footer of a dataTable
ilya_shaikovsky Aug 25, 2010 2:28 AM (in response to kado)1) so you should just avoid calling data from db every time it's called by component. It occurs a few times during lifecycle according to jsf spec.
2) not sure that get the point.. if you performing some calls to dataMode in your actions/listeners - data already populated to the model(at update model phase) - so you should get with the new data already.
-
7. Re: Displaying total sums in the footer of a dataTable
kado Aug 25, 2010 9:02 AM (in response to ilya_shaikovsky)So, I hope it will be clearer with my example code (only for testing my problem):
test.xhtml:
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich"> <ui:composition template="/templates/standard-layout.xhtml"> <ui:define name="title">Test</ui:define> <ui:define name="caption">Test</ui:define> <ui:define name="body"> <h:form> <rich:dataTable id="table" binding="#{overview.dataTable}" value="#{dataModel}" var="test" onRowMouseOver="this.style.backgroundColor='#F1F1F1'" onRowMouseOut="this.style.backgroundColor='#{a4jSkin.tableBackgroundColor}'" reRender="footer"> <f:facet name="header"> <rich:columnGroup> <rich:column> <h:outputText value="Name" /> </rich:column> <rich:column> <h:outputText value="Value" /> </rich:column> </rich:columnGroup> </f:facet> <rich:column filterBy="#{test.name}" filterEvent="onkeyup"> <h:outputText value="#{test.name}" /> </rich:column> <rich:column> <h:outputText value="#{test.values.size()}" /> </rich:column> <f:facet name="footer"> <rich:columnGroup> <rich:column> <h:outputText value="Total" /> </rich:column> <rich:column id="footer"> <h:outputText value="#{overview.total}" /> </rich:column> </rich:columnGroup> </f:facet> </rich:dataTable> </h:form> </ui:define> </ui:composition> </html>
OverviewBean.java:
@Named("overview") @ViewScoped public class OverviewBean { private HtmlDataTable dataTable; public HtmlDataTable getDataTable() { return dataTable; } public void setDataTable(HtmlDataTable dataTable) { this.dataTable = dataTable; } public String getTotal() { DataModel dm = DataModel.class.cast( dataTable.getValue() ); return String.valueOf( dm.getDataItems().size() ); } }
BaseModifiableDataModel.java:
public abstract class BaseModifiableDataModel<T> extends ExtendedDataModel implements Modifiable { @PersistenceContext(unitName = "test") private EntityManager manager; private Class<T> entityClass; public BaseModifiableDataModel(Class<T> entityClass) { super(); this.entityClass = entityClass; } private List<T> dataItems = new ArrayList<T>(); private T dataItem; private SequenceRange cachedRange; private List<T> cachedItems = new ArrayList<T>(); private List<FilterField> filterFields; private List<SortField2> sortFields; private static boolean areEqualRanges(SequenceRange range1, SequenceRange range2) { if (range1 == null || range2 == null) { return range1 == null && range2 == null; } else { return range1.getFirstRow() == range2.getFirstRow() && range1.getRows() == range2.getRows(); } } private CriteriaBuilder createCriteriaBuilder() { return manager.getCriteriaBuilder(); } private void appendFilters(FacesContext ctx, CriteriaBuilder criteriaBuilder, CriteriaQuery<T> criteriaQuery, Root<T> instance) { if (filterFields != null) { List<Predicate> predicates = new ArrayList<Predicate>(); for (FilterField filterField : filterFields) { String propertyName = getPropertyName( ctx, filterField.getExpression() ); String filterValue = ((ExtendedFilterField) filterField).getFilterValue(); if (filterValue != null && filterValue.length() != 0) { Path<String> filter = instance.get( propertyName ); predicates.add( criteriaBuilder.like( criteriaBuilder.lower( filter ), "%" + filterValue.toLowerCase() + "%" ) ); } } Predicate[] predicateArray = new Predicate[predicates.size()]; for (int i = 0; i < predicates.size(); i++) { predicateArray[i] = predicates.get( i ); } criteriaQuery.where( predicateArray ); } } private void appendSorts(FacesContext ctx, CriteriaBuilder criteriaBuilder, CriteriaQuery<T> criteriaQuery, Root<T> instance) { if (sortFields != null) { List<Order> orders = new ArrayList<Order>(); for (SortField2 sortField : sortFields) { Ordering ordering = sortField.getOrdering(); if (Ordering.ASCENDING.equals( ordering ) || Ordering.DESCENDING.equals( ordering )) { String propertyName = getPropertyName( ctx, sortField.getExpression() ); Path<String> path = instance.get( propertyName ); orders.add( Ordering.ASCENDING.equals( ordering ) ? criteriaBuilder.asc( path ) : criteriaBuilder.desc( path ) ); } criteriaQuery.orderBy( orders ); } } } private String getPropertyName(FacesContext ctx, Expression expression) { return ctx.getApplication().evaluateExpressionGet( ctx, expression.getExpressionString(), String.class ); } @Override public Object getRowKey() { return dataItem; } @Override public void setRowKey(Object key) { this.dataItem = entityClass.cast( key ); } @SuppressWarnings("unchecked") @Override public void walk(FacesContext ctx, DataVisitor visitor, Range range, Object argument) throws IOException { SequenceRange sequenceRange = (SequenceRange) range; if (this.cachedItems == null || !areEqualRanges( this.cachedRange, sequenceRange )) { CriteriaBuilder criteriaBuilder = createCriteriaBuilder(); Metamodel model = manager.getMetamodel(); EntityType<T> entity = model.entity( entityClass ); CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery( entityClass ); Root<T> instance = criteriaQuery.from( entity ); appendFilters( ctx, criteriaBuilder, criteriaQuery, instance ); appendSorts( ctx, criteriaBuilder, criteriaQuery, instance ); Query query = manager.createQuery( criteriaQuery ); if (sequenceRange != null) { int first = sequenceRange.getFirstRow(); int rows = sequenceRange.getRows(); query.setFirstResult( first ); if (rows > 0) { query.setMaxResults( rows ); } } this.cachedRange = sequenceRange; this.cachedItems = query.getResultList(); } this.dataItems.clear(); for (T item : this.cachedItems) { visitor.process( ctx, item, argument ); this.dataItems.add( item ); } } @Override public int getRowCount() { return cachedItems.size(); } @Override public Object getRowData() { return this.dataItem; } @Override public int getRowIndex() { return -1; } @Override public Object getWrappedData() { return null; } @Override public boolean isRowAvailable() { return (this.dataItem != null); } @Override public void setRowIndex(int rowIndex) { } @Override public void setWrappedData(Object data) { } @Override public void modify(List<FilterField> filterFields, List<SortField2> sortFields) { this.filterFields = filterFields; this.sortFields = sortFields; this.cachedItems = null; this.cachedRange = null; } public List<T> getDataItems() { return dataItems; } }
DataModel.java:
@Named("dataModel") @Dependent public class DataModel extends BasisModifiableDataModel<Test> { public DataModel() { super( Test.class ); } }
The getDataItems() method is called before walk() is called, so I get an empty List of the items in OverviewBean - at every time. Please tell me, how I can rewrite my example to solve the problem. Either I'm too stupid, or JSF is not suitable for problems like that.
-
8. Re: Displaying total sums in the footer of a dataTable
ilya_shaikovsky Aug 26, 2010 8:11 AM (in response to kado)I think you should use just something like
return String.valueOf( dm.getRowCount() );
And your model should return count of data properly. At livedemo that method implemented like:
@Override public int getRowCount() { Criteria criteria = createCriteria(); appendFilters(FacesContext.getCurrentInstance(), criteria); criteria.setProjection(Projections.rowCount()); //There are cast to Number object, related to http://opensource.atlassian.com/projects/hibernate/browse/HHH-3497. //Such kind of implementation should work undependent on what Hibernate library version used. return ((Number)criteria.list().get(0)).intValue(); }
-
9. Re: Displaying total sums in the footer of a dataTable
kado Aug 26, 2010 9:57 AM (in response to ilya_shaikovsky)You're right. I was really too stupid for it. I have changed the DataModel using caching, now it does not care which method is called first. Also it is invoked only one query per filter event. The performance is no worse than the original one now...
But another problem had to be dealt with this changes. Thus I used JPA 2 with a JEE 6 Environment, I couldn't use @Named on my DisplayBean, because it allows no other Scope as @Dependent. So I had to define a @ManagedBean with @ViewScoped. I can't explain why is this so. The only disadvantage now is because of mixing different technologies.
I would like to thank you for the great support here in the forum. This is main reason why we are using Richfaces in our company.
But one feature I'd like to have at Data Tables: Support for an "ajax delay" on filter events. It looks not very nice if someone types to fast.
Thanks,
Jan
-
10. Displaying total rowCount of a dataTable
anudeepshetty Feb 22, 2011 5:02 AM (in response to cmathrusse)I have similar kind of issue with my code ,
i want to render the datascroller of the datatable only if the row count exceeds 5(number of values in the list are >5). currently i use a backing bean variable and render the scroller if backingvariable > 5 , backingvariable=list.size().
Is there any other way i could get the total row count instead of using the backingvariable.
?
-
11. Re: Displaying total rowCount of a dataTable
danielk Mar 1, 2011 4:45 PM (in response to anudeepshetty)rich:dataTable is an exciting tag. One of its capabilites is rowKeyVar. With this setting you can output the total count of rows of your table (also with filtering). Just add two things to your rich:dataTable:
{code}<rich:dataTable
id="myTable"
binding="#{myBean.dataTable}"
rowKeyVar="rowCount"
...{code}
Than you can use the binding in combination with rowKeyVar to show total amount of rows:
{code}<h:outputText value="#{myBean.dataTable.rowCount}"/>{code}
For the datascroller problem: the datascroller has a property called "renderIfSinglePage". All you have to do is configure this to false, and give your dataTable a maximum of "rows". Than datascroller will only be rendered if datatable contains more rows than defined.