Provides a declarative way of defining Data Grids.
It works currently with jqGrid, google visualization and jQuery dataTables.
Out of the box it provides sorting, filtering, exporting and inline edit just by declaring a grid in a controller and adding a tag to your gsp.
It also provides a powerful selection widget (a direct replacement for drop-boxes)
Official plugin page on Grails portal
Add the following plugin dependencies to your BuildConfig.groovy
repositories {
...
// required by a dependency of the export plugin
mavenRepo "http://repo.grails.org/grails/core"
}
...
grails.project.dependency.resolution = {
plugins {
...
// EasyGrid plugin http://grails.org/plugin/easygrid
compile ":easygrid:1.6.6"
// For minimum functionality you need: jquery-ui and the export plugins.
// Export Plugin http://grails.org/plugin/export
compile ":export:1.6"
// jQuery UI Plugin http://grails.org/plugin/jquery-ui
compile ":jquery-ui:1.10.3"
// For google visualization you also need google-visualization
// Google Visualization API Plugin http://grails.org/plugin/google-visualization
compile ":google-visualization:0.7"
...
}
}
Check latest published version on Grails plugin portal.
After installation you need to run grails easygrid-setup
command.
This will append the grid templates in the /templates/easygrid folder, where you can customize them. And it will also add the '/conf/EasygridConfig.groovy' file - where you can add general settings.
The issues that Easygrid tackles are:
Easygrid solves these problems by proposing a solution based on declarations & conventions.
The entire grid logic is defined in the Controller (or in an outside file) using the provided custom builder. (some particular view aspects can be defined in the gsp, using the provided taglibs)
For each grid you can configure the following aspects:
The plugin provides a clean separation between the model and the view (datasource and rendering) Currently there are implementations for 3 datasources (GORM , LIST - represents a list of objects stored in the session (or anywhere), CUSTOM ) and 4 grid implementations (JqGrid, GoogleVisualization, Datatables, static (the one generated by scaffolding))
All grids will be defined in controllers - which must be annotated with @Easygrid .
In each controller annotated with @Easygrid
you can define a static closure called grids
where you define the grids which will be made available by this controller.
Starting with version 1.4.1, the preferred way of defining grids is by using plain closures ending with the Grid
suffix (similar to flows in Spring WebFlow)
The plugin provides a custom Builder for making the configuration very straight forward.
Example from the petclinic sample:
def ownersGrid = {
domainClass Owner
columns {
id {
type 'id'
enableFilter false
}
firstName
lastName
address
city
telephone
nrPets {
enableFilter false
value { owner ->
owner.pets.size()
}
jqgrid {
sortable false
}
}
}
}
In the gsp, you can render this grid via the following tag:
<grid:grid name="owners" addUrl="${g.createLink(controller: 'owner', action: 'add')}">
<grid:set caption="Owners" width="800"/>
<grid:set col="id" formatter="f:customShowFormat" />
<grid:set col="nrPets" width="60" />
</grid:grid>
<grid:exportButton name="owners"/>
You also have to add the resource modules for the grid implementation:
<r:require modules="easygrid-jqgrid-dev,export"/>
From this simple example, you can see how we can define almost all aspects of a grid in a couple of lines. (datasource, rendering, export properties, filtering)
Custom UI properties can be added to the Config file (as defaults or types), in the Controller, or in the gsp page.
The simple grid from this example - which can be viewed here, comes with all features - including basic default filtering.
jqgrid
implements jqGridvisualization
implements google visualization datatabledatatables
implements datatablesclassic
implements the classic grails grid (the static one generated by scaffolding)To create your own implementation you need to:
Config.goovy
On installation of the plugin, the renderer templates for the default implementations are copied to /grails-app/views/templates/easygrid
from the plugin, to encourage the developer to customize them.
gorm
For fast mock-up , grids with this type can be defined without columns, in which case these will be generated at runtime from the domain properties (dynamic scaffolding).
A filter closure is defined per column and will have to be a closure which will be used by a GORM CriteriaBuilder Starting from version 1.5.0 this datasource works only with Hibernate!
list
The filterClosure takes 2 parameters: the Filter object and the actual row - and returns true if the row matches the filter
custom
If you want to create your own datasource (skip this as a beginner):
Create a service - which must implement the following methods:
generateDynamicColumns() - optional - if you want to be able to generate columns
verifyGridConstraints(gridConfig) - verify if the config is setup properly for this datasource impl
list(Map listParams = [:], filters = null) - ( * returns the list of rows
countRows(filters = null)
in case you want to support inline editing you need to define 3 closures (updateRow
, saveRow
, delRow
)
The name of each column will be the actual name of the closure. Beside the actual column name, from the name property other properties can be inferred, like:
name
will be used as the column property (see below)name
(in case you want to override some properties in the taglib - see below)name
is also used as the name of the http parameter when filtering or sorting on a columnColumn Label:
The label can be defined , but in case it's missing it will be composed automatically using the 'labelFormat' template - defined in Config.groovy
. ( see comments in Config.groovy
)
Column Value: For each column you have to define the value that will be displayed in the cell. There's 2 options for this: In case the type of the grid is "gorm" or "list", and you just want do display a plain property you can use "property".
Otherwise you need to use the "value" closure, whose first parameter will be the actual row, and it will return whatever you need.
(There is a possibility to define the "property" columns more compact by using the actual property as the name of the column )
enableFilter - if this columns has filtering enabled
filterFieldType - one of the types defined per datasource - used to generate implicit filterClosures. In case of gorm the type can be inferred
filterClosure: When the user filters the grid content, these closures will be applied to the dataset. In case of grid type = gorm, the search closure is actually a GORM CriteriaBuilder which will be passed to the list method of the domain.
Easygrid also comes integrated with the Export Plugin This plugin has different settings for each export format , which can pe declared in the config file or in the grid.
Each column has an optional export section, where you can set additional properties like width, etc.
From the example you can also notice the type property of a column. Types are defined in Config.groovy, and represent a collection of properties that will be applied to this column, to avoid duplicate settings.
Default values:
The format to apply to a value is chosen this way:
If you define the property securityProvider : then it will automatically guard all calls to the grid
Easygrid comes by default with a spring security implementation. Using this default implementation you can specify which roles are allowed to view or inline edit the grid
You can customize every aspect of the grid - because everything is a property and can be overriden. You can also add any property to any section of the configuration, and access it from the customizable template (or from a custom service, for advanced use cases)
The Selection widget is meant to replace drop down boxes (select) on forms where users have to select something from a medium or large dataset. It is composed from a jquery autocomplete textbox ( which has a closure attached on the server side) and from a selection dialog whith a full grid (with filtering & sorting), where the user can find what he's looking for, in case he can't find it using the fast autocomplete option. It can also by constrained by other elements from the same page or by statical values. ( for ex: in the demo , if you only want to select from british authors)
You can use any grid as a selection widget by configuring an "autocomplete" section (currently works only with jqGrid and GORM)
Like this:
autocomplete {
idProp 'id' // the id property
labelValue { val, params -> // the label can be a property or a closure ( more advanced use cases )
"${val.name} (${val.nationality})"
}
textBoxFilterClosure { // the closure called when a user inputs a text in the autocomplete input
ilike('name', "%${params.term}%")
}
constraintsFilterClosure { params -> // the closure that will handle constraints defined in the taglib ( see example)
if (params.nationality) {
eq('nationality', params.nationality)
}
}
}
Easygrid provies the following tags:
<grid:grid name="grid_name">
will render the taglib - see doc<grid:exportButton name="grid_name">
the export button - see doc
has all the attributes of the export tag from the export plugin, plus the name of the grid<grid:selection>
renders a powerful replacement for the standard combo-box see the taglib document (see doc and Example)In each annotated controller, for each grid defined in "grids" , the plugin injects multiple methods:
def ${gridName}Html()
def ${gridName}Rows()
def ${gridName}Export()
def ${gridName}InlineEdit()
def ${gridName}AutocompleteResult()
def ${gridName}SelectionLabel()
on installing the plugin it will copy 4 templates ( one for each renderer) in your /templates/easygrid folder
You are encouraged to customize the templates so that the layout matches your needs
also, in the configuratin folder there will be a file : EasygridConfig
The GridConfig object ( which defines one grid ) is designed so that you can add new properties to the grid or to any column. These properties that you add, can be accessed in the renderer templates to customize the view. The default behavior is that all the properties added in the jqgrid {} section ( or visualization, etc, ) will be automatically added to the created javascript object ( only use properties available in the library documentation )
A: First you need to annotate a controller with @Easygrid
, and define the desired grid def gridNameGrid = {..}
In the gsp (if it belongs to that controller), all you have to do is:
1) add <r:require modules="easygrid-jqgrid-dev,export"/>
(or whatever impelementation you're using)
2) <grid:grid name="gridName"/>
A: Check out GridConfig.groovy
A: Check out Filter.groovy.
A: Because on this implementation you also get the current row so that you can apply the filter on it, as opposed to the gorm implementation where the filter closure is a gorm criteria.
A: You don't have to put view stuff in the controller. You are encouraged to define column types and as many default view properties as possible in the config file. Also , you can override or set any view property in the grid tag in the gsp.
A: No problem, everything is extensible, just put it in the builder, and you can access it in the template.
A: Yes you can. If there is no securityProvider defined, then no security restrictions are in place.
A: Yes, you can override the defined grid properties from the taglib. Check out the taglib section.
A: No problem, you can replace the export service with your own.
A: Yes.
A: The labelFormat is transformed into a SimpleTemplateEngine instance and populated at runtime with the gridConfig and the prefix.
A: All public methods are guarded by the security provider you defined either in the config or in the grid. You can also apply your own security filter on top of the generated controller actions.
A: The JqGrid plugin is a thin wrapper over JqGrid. It provides the resources and a nice taglib. But you still have to code yourself all the server side logic. Easygrid does much more than that.
A: If you already use jqgrid, then you probably have the grid logic split between the controller and the view. If you have inline editing enabled, then you probably have at least 2 methods in the controller. Basically, you need to strip the grid to the minimum properties ( the columns and additional properties) , translate that intro the easygrid builder and just use the simple easygrid taglib. If, after converting a couple of grids, you realize there's common patterns, you are encouraged to set default values and define column types, to minimize code duplication. After the work is done, you will realize the grid code is down to 10%.
A: You can create a gsp template just for it and set it in the builder.
A: It's designed to be flexible.
A: Yes, it's pretty easy, it's justa matter of replacing the select tag . Nothing needs to be changed in the controller
A: Just create a new autocomplete renderer template and use the selection jquery ui widget
A: You can raise a github ticket, drop me an email to: tudor.malene@gmail.com, or use the grails mailing list
Bugs:
Improvements:
Bugs:
Improvements:
Bugs:
Bugs:
Bugs:
Bugs:
Bugs:
Improvements:
Bugs:
Bugs:
Improvements:
Bugs:
Improvements:
Bugs:
Improvements:
Improvements:
Bugs:
Bugs:
Improvements:
Bugs:
Improvements:
Bugs:
Improvements:
Improvements:
float
, double
, BigDecimal
, long
and int
Improvements:
Bugs:
format
parameter clashes)Improvements:
Bugs:
Improvements:
DefaultEasygridConfig.groovy
class. The custom project settings will be in /grails-app/conf/EasygridConfig
Bugs:
@Easygrid
instead of @EasyGrid
_jqGridRenderer.gsp
You can add the resources via the resources plugin like this: <r:require modules="easygrid-jqgrid-dev,export"/>
,
or via the assets-pipeline plugin like:
<asset:javascript src="https://github.com/tudor-malene/Easygrid/raw/master/easygrid.jqgrid.js"/>
<asset:stylesheet src="https://github.com/tudor-malene/Easygrid/raw/master/easygrid.jqgrid.css"/>
<asset:stylesheet src="https://github.com/tudor-malene/Easygrid/raw/master/export.css"/>
The convention is: 'easygrid.${implementation}.[js/css]' For the selection widget you have to add: 'easygrid.selection.js' together with jqgrid
Merge _jqGridRenderer.gsp
and/or _dataTablesGridRenderer.gsp
Merge _dataTablesGridRenderer.gsp
Merge _jqGridRenderer.gsp
and/or _dataTablesGridRenderer.gsp
This version will break only custom inline edit closures. To upgrade you need to add a second parameter to saveRowClosure, updateRowClosure or delRowClosure. This parameter will be of type InlineResponse. In order to send messages to the UI you will need to use this object instead of the return values. Checkout the reference implementation: GormDatasourceService.updateRow
This is a major update and it will break existing grids. Please let me know ASAP if you have problems upgrading First of all check the petclinic example: and the example repositories.
/conf/EasygridConfig.groovy
updateRowClosure
, etc.) - the fist parameter of the closure will be the actual gridConfig
object Config.groovy
:
/templates/easygrid
folder (and the default configuration was updated too)@Easygrid
Config.groovy
labelFormat = '${labelPrefix}.${column.name}.label'
Apache v2