...
Issue: http://issues.qcadoo.org/browse/QCADOO-56
Requirements
As a developers I would like to have the ability to insert a custom dataset to the grid component in a way that would preserve its filter and pagination functionality if possible.
...
3. Grids with complex filters (medium requirement)
4. Grids with datasets calculated in Java (medium requirement)
5. Fully with unspecified columns (week very weak requirement)
Like in the module: http://wiki.qcadoo.org/display/QCDMESBLP/Custom+query+module
Furthermore:
Filters should always be automatically supported entity fields in the modelName.
It would be good if filter could also be automatically supported in simple attributes in the select statement but this is not a must.
I should however be able to take the string from the filter and implement it my self.
This also goes for ordering.
Suggested mechanism
Info |
---|
This is a pseudo-code solution suggested by the person who analyzed the issue. Developers who implement this issue should design the detail solution for the requirements and may come to an solution which is very different from this one. However it should offer the same possibility as the example shown here or if should be discussed if the detail solution could be less powerful to make the implementation simpler. |
The solution should be available as an Java API available to hook which would be responsible for preparing the data for a table.
1. Entity centric grids but with some additional calculated columns
Here we still want to preserve the functionality we had in view XML (correspontingView, using fields from modelView, etc.) but we would also like to have columns that are supplied by the query.
Code Block | ||||
---|---|---|---|---|
| ||||
<component type="grid" name="orderGroups" reference="grid">
<option type="column" name="number" fields="number" link="true" />
<option type="column" name="name" fields="name" link="true" />
<!-- suggested option for an column from a custom dataset, the main entity must always be in the 0 column index -->
<option type="column" name="ordersCount" datasetColumIndex="1" />
<option type="column" name="dateFrom" fields="dateFrom" />
<option type="column" name="dateTo" fields="dateTo" />
<option type="order" column="name" direction="asc" />
<option type="correspondingView" value="orderGroups/orderGroupDetails" />
<option type="correspondingComponent" value="form" />
<option type="searchable" value="name,number,dateFrom,dateTo" />
<option type="orderable" value="name,number,dateFrom,dateTo" />
<option type="fullscreen" value="true" />
<option type="multiselect" value="true" />
</component>
|
Code Block | ||
---|---|---|
| ||
loadOrderGroups(viewState) {
grid = viewState.getComponentByReference("orderGroupsGrid");
// expanded Hibernate or JPA criteria builder
criteriaBuilder = someService.getCriteriaBuilder();
criteriaQuery = criteriaBuilder.createQuery();
from = criteriaQuery.from("orderGroup");
min = criteriaBuilder.min(from.get("orders"));
// the 'modelName' entity must be always first
criteriaQuery = criteriaQuery.multiselect(from, min);
// this would apply criteria from the grids filter but not pagination yet
criteriaQuery = someService.applyGridFilterCriteria(criteriaQuery, grid);
query = someService.createQuery(criteriaQuery);
// list() dosn't fetch data from the db, it just prepares the list
// object which in fact is a proxy to the database
datasetSize = query.list().size();
query.setFirstResult(grid.getFirstResult());
query.setMaxResults(grid.getMaxResults());
// the first get from the list will actualy call select on the db
// remember that in this case this is actually a List<Object[]>
grid.setDatasetPage(query.list());
grid.setDatasetSize(datasetSize);
}
|
2. Fully calculated girds
Code Block | ||||
---|---|---|---|---|
| ||||
<component type="grid" name="inventory" reference="grid">
<option type="column" name="warehouse" datasetColumIndex="0" />
<option type="column" name="product" datasetColumIndex="1" />
<option type="column" name="quantity" datasetColumIndex="2" />
<option type="order" column="warehouse" direction="asc" />
<option type="searchable" value="warehouse,product" />
<option type="orderable" value="warehouse,product" />
</component> |
Code Block | ||
---|---|---|
| ||
loadInventory(viewState) { grid = viewState.getComponentByReference("inventoryGrid"); criteriaBuilder = someService.getCriteriaBuilder(); // my method that prepares a query criteriaQuery = preapreBaseInventoryCriteriaQuery(criteriaBuilder); searchFilters = grid.getSearchFilters() // my method to add the right criteria criteriaQuery = applyInventorySearchFilters(criteriaQuery, searchFilters); ordering = grid.getOrdering(); // my method to add the right criteria criteriaQuery = applyInventoryOrderFilters(criteriaQuery); query = someService.createQuery(criteriaQuery); datasetSize = query.list().size(); query.setFirstResult(grid.getFirstResult()); query.setMaxResults(grid.getMaxResults()); grid.setDatasetPage(query.list()); grid.setDatasetSize(datasetSize); } |
3. Grids with complex filters
Code Block | ||
---|---|---|
| ||
loadForComplexFilter(viewState) {
grid = viewState.getComponentByReference(...);
complexFilter = viewState.getComponentByReference(...);
complexFilterString = complexFilter.getValue();
criteriaBuilder = someService.getCriteriaBuilder();
criteriaQuery = criteriaBuilder.createQuery();
from = criteriaQuery.from("someEntity");
criteriaQuery = criteriaQuery.select(from);
criteriaQuery = someService.applyGridFilterCriteria(criteriaQuery, grid);
// my method to add the right criteria
criteriaQuery = applyComplexFilter(criteriaQuery, criteriaBuilder);
query = someService.createQuery(criteriaQuery);
datasetSize = query.list().size();
query.setFirstResult(grid.getFirstResult());
query.setMaxResults(grid.getMaxResults());
grid.setDatasetPage(query.list());
grid.setDatasetSize(datasetSize);
} |