Grid

Awesome Grid is declared using the Html.Awe().Grid helper, its columns can be bound to one or multiple properties and sub-properties of the model, it has sorting, grouping, header and footer aggregates, paging and client side api. It can also be bound to parents ( used for filtering ) and parameters ca be set as well.

Data binding

It needs an url specified to get data from, if not specified by default convention it will look for a controller with the same name as it + "Grid"/GetItems, example:
@Html.Awe().Grid("DinnerGrid").Columns(...) // gets data from DinnerGrid/GetItems

@Html.Awe().Grid("MyGrid")
           .Url(Url.Action("GetItems", "LunchGrid")) // gets data from LunchGrid/GetItems
           .Columns(...)               
the url has to return a Json made from the result of
GridModelBuilder<TModel>().Build()
, example:
public class LunchGridController : Controller
{
    public ActionResult GetItems(GridParams g)
    {
        var list = Db.Lunches.AsQueryable();

        return Json(new GridModelBuilder<Lunch>(list, g)
            {
                Key = "Id", // needed for Entity Framework, nesting, tree, grid api (select, update)
                // EF can't do paging unless it orders at least by one column so we will order by that column when there is no sorted columns
            }.Build());
    }
}
The model defined in
GridModelBuilder<Model>
is the one that is used for databinding, the
Column.Bind
has to be defined based on the Model's properties, like this:
 .Columns(
     new Column{ Bind = "Id" }, // bind to Model.Id                  
     new Column{ Bind = "Location" }, // bind to Model.Location
     new Column{ Bind = "Country.Name" } // bind to Model.Country.Name
     new Column{ Bind = "Person.FName,Person.LName" } // bind to Model.Person.FName and Model.Person.LName
     /* when sorting/grouping the FName will have a +1 higher rank than LName*/
     new Column{ Bind = "Code1,Code2" } // bind to Model.Code1 and Model.Code2
the grid uses DynamicLinq so with EntityFramework sorting by a column that is bound to Person.FName,Person.LName would be like calling .OrderBy(o => o.Person.FName).ThenBy(o => o.Person.LName) , unless you're using custom querying, in that case you would handle this yourself.

Map

The model that is displayed and the model that the columns are bound to don't have to be the same, you can define a
Map
function that will transform the grid
querying model
(the generic type defined in
GridModelBuilder<T>
) into the a
display model
(the type returned by
Map
), this can be useful in many cases: - to generate a model property based on other properties and parameters - when a
Column
is bound to multiple or nested model properties - to optimise/reduce the amount of data being sent to the client (send only what you need to display/or use in js) - to avoid the circular reference error when serialising the model to json here's an example:
return Json(new GridModelBuilder<Lunch>(list, g)
    {                   
        Map = o => new
        {
            o.Id // grid key
            CountryName = o.Country.Name, // =>  Bind = "Country.Name" and ClientFormat = ".(CountryName)"
            ChefName = o.Chef.FirstName + " " + o.Chef.LastName // here ClientFormat = ".(ChefName)" (value displayed), but Bind = "Chef.FirstName,Chef.LastName"
                                                               // so the sorting/grouping on this column is bound to Chef.FirstName and Chef.LastName
            o.Person // this can be just Bind="Person"
            }
    }.Build());

Custom Formatting

By default the cell content will show the value of the model property defined in
Column.Bind
, but that can be changed by specifying:
ClientFormat
- format defined as a string which can include row model properties defined like this:
.(Prop1)
ClietnFormatFunc
- define a js function that will receive a the row model and
Bind
value as parameters, and must return a string which will be used a value for the cell. The result of the javascript function will not be encoded. examples:
// 123 USD | .(Cost) means Cost property value from the display model (usually the model returned by Map)
new Column{ Bind = "Cost", ClientFormat = ".(Cost) USD" },

// Adam spent 123
new Column{ Bind = "Person", ClientFormat = ".(Person) spent .(Cost) $" },

// will call formatPrice(model, "Price"), result will be <div style='color:red;'>123 £ </div>
new Column{ Bind = "Price", ClientFormatFunc = "formatPrice"},
...
<script type="text/javascript">
    function formatPrice(lunch) {
        var color = 'blue';
        if (lunch.Price < 20) color = 'green';
        if (lunch.Price > 50) color = 'red';
        return "<div style='color:" + color + ";'>" + lunch.Price + " USD </div>";
    }
</script>

Row class

A css class can be set to individual rows using
.RowClassClientFormat
, here's an example:
@Html.Grid("Grid1").RowClassClientFormat(".RowClass")...
and in the controller have this:
return Json(new GridModelBuilder<Lunch>(Db.Lunches.AsQueryable(), g)
{
    Map = o => new
    {
        ...
        RowClass = o.Price > 90 ? "pinkb" : o.Price < 30 ? "greenb" : string.Empty
    }
In this example the model will have the
RowClass
property which will have a different value depending on the Price property and the RowClassClientFormat will use that value to set the css class for the row.

Encoding

By default cell content is html encoded, but there are exceptions. The result of the
ClientFormtFunc
js function is not encoded, you can also set
.Encode(false)
to disable html encoding for the whole grid.

Persistence

Enable the persistence using this extension:
.Persistence
- will save the state of the grid (columns, current page, collapsed groups). There are 3 types of persistence:
View
- data will be lost after refresh, go to another page
Session
- data will be lost after closing the browser (uses sessionStorage)
Local
- data will be persisted even after closing the browser (uses localStorage) When using it make sure you don't have 2 grids with the same persistence key , persistence key is equal to grid's name by default, but you can set it using
.PersistenceKey
All keys used for saving are prefixed by the
awe.ppk
string, so when you're deploying a new version you can modify the
awe.ppk
string. Right now the
aweUtils.init
method will remove all localStorage keys that start with "awe" and don't start with the value of
awe.ppk
(`awe.ppk` by default is set to "awe" + number), so you could do this:
awe.ppk += "myapp" + 5; // 5 is version, modify it on each release
aweUtils.init(...
You only need to do this (set awe.ppk) if you're using Local or Session persistence.

Sorting

The grid is sortable by default, this can be changed by setting the
Sortable
for the grid or for a column:
Column { Bind = "Id", Sortable = false }
@Html.Grid("MyGrid").Sortable(false) // Column.Sortable overrides this value
for single column sorting use the extension
SingleColumnSort
:
@Html.Grid("MyGrid").SingleColumnSort(true)
other sorting related properties of the column:
Column.Sort
- initial sorting for this column (None | Asc | Desc)
Column.SortRank
- initial sort rank/priority for this column

Default Key sorting

When setting
GridModelBuilder.Key
or
KeyProp
the data by default will be sorted by the
Key
, this is because the data needs to always be sorted by at least 1 column before doing paging (Take/Skip), you can change this by setting
GridModelBuilder.DefaultKeySort
, example:
new GridModelBuilder<Meal>(...) { Key = "Id", DefaultKeySort = Sort.None }

Grouping

Just like with sorting, all the properties ( that have a Bind defined ) are groupable by default, but this can be changed by setting Column properties Column.Group - defines whether initially the column is grouped Column.GroupRank - group rank for this column Column.GroupRemovable - (default is true) if set to false grouped column won't have the remove group button

Aggregates

You can put aggregates in the header and footer of the groups, to do that you have to define functions for the MakeHeader and MakeFooter properties of the GridModelBuilder:
public class GroupingGridController : Controller
{
    public ActionResult GetItems(GridParams g)
    {
        //passing 2 Functions MakeFooter and MakeHeader
        return Json(new GridModelBuilder<Lunch>(Db.Lunches.AsQueryable(), g)
        {
            MakeFooter = MakeFooter,
            MakeHeader = gr =>
            {
                //get first item in the group
                var first = gr.Items.First();
                
                //get the grouped column value for the first item
                var val = AweUtil.GetColumnValue(gr.Column, first).Single();
                
                return new GroupHeader
                {
                    Content = string.Format(" {0} : {1} ( Count = {2}, Max Price = {3} )",
                                            gr.Header, val, gr.Items.Count(), gr.Items.Max(o => o.Price)),
                    Collapsed = true // making groups collapsed by default
                };
            }
        }.Build());
    }

    private object MakeFooter(GroupInfo<Lunch> info)
    {
        //will add the word Total at the grid level footer (Level == 0)
        var pref = info.Level == 0 ? "Total " : "";

        return new
                {
                    Food = pref + " count = " + info.Items.Count(),
                    Location = info.Items.Select(o => o.Location).Distinct().Count() + " distinct locations",
                    Date = pref + " max: " + info.Items.Max(o => o.Date).Date.ToShortDateString(),
                    Price = info.Items.Sum(o => o.Price)
                };
    }

}

Api

Access the api by calling :
var api = $('#gridId').data('api');

api.load({
    group:[columnName,..],
    sort: [{Prop: columnName, Sort: direction }, ..],// direction 0 = none, 1 = asc, 2 = desc
    params: {PropName:PropValue, ..},// params will persist until api with params: {} is called
    oparams: {PropName:PropValue, ..} // oparams - one time params, sent only when the api is called with it
})
// all properties( group, sort, params, oparams) are optional, specifying a property will override its previous value

api.reset() // reset will bring the grid back to the initial state defined in the markup
api.getRequest() // get last request
api.getResult() // get last result
api.clearPersist() // clear grid persistence data
api.persist() // persist grid state
api.render() // render grid using last successful result
api.select(key) // select grid row(s) by key (multiple rows can be selected in case of the treeGrid), returns an array of jQuery objects
api.update(key[, params]) // update item by key, additional params can be sent
api.lay() // adjust grid layout
api.getSelection() // get selected rows models
api.nestOpen($row, nestName) // open row nest
api.nestClose($row, nestName) // close row nest
api.model($row) // get row model

api.inlineSave($row) // inline save grid row

api.batchSave($rows) // inline batch save, when $rows not specified all rows in edit mode will be saved

api.inlineCancel($row) // cancel inline edit row
api.inlineCancelAll() // cancel all inline edit rows
api.inlineEdit($row) // inline edit row

// grid configuration can also be accessed via data('o');

Events

awebeginloadbegin loading, before sending request
aweloadgrid was loaded
awecolresizeresizing grid column
awecolresizeendfinished resizing column
awerendergrid rendered
awebfrenbefore grid render
awereordercolumn reordered
aweupdategrid row updated
awenestloadgrid nest loaded
aweinlinecancelinline edit grid row canceled
aweinlineeditgrid row entered inline edit mode
aweinlinesaveinline edit grid row saved
example:
$('#Grid1').on('aweload', function (event, data, requestData) {
        console.log('aweload handled', data, requestData);
    }).on('awebeginload', function (event, requestData) {
        console.log('awebeginload handled', data, requestData);
    });

Extensions

UrlSpecify the url from where to load data from
HeightSet height of the grid, when set the grid will be scrollable. When not specified (or zero) the grid will automatically scale it's height
ColumnsSpecify the columns of the Grid
PageSizeSet the page size
ShowGroupedColumnShow the columns that are grouped by (default true)
SingleColumnSortenables sorting by one column at a time
Persistencemakes the grid save it's state ( collapsed groups, current page, sorting, grouping), it can be None - no persistence, View - view context (will loose state on page refresh); Session - using HTML sessionStorage (will loose state on closing browser); Local - using HTML localStorage ( state will be persisted even after the browser is closed)
PrefixSet Prefix for the html id (use to achieve unique ids for elements with same name)

Column properties

Bindused to bind this column to the model, it can be bound to one or more properties and subproperties in the model, examples: "FirstName", "FirstName,LastName", "Country.Name", "Chef.FirstName, Chef.LastName"
Groupdefines whether initially the column is grouped
GroupRankgroup rank for this column
GroupRemovable(default is true) if set to false grouped column won't have the remove group button
Sortinitial sorting for this column (None | Asc | Desc)
SortRankinitial sort rank for this column
ClientFormatClient format for the column defined as a string using
.(ModelPropertyName)
for including values of the row model
ClientFormatFuncDefines the Name of a javascript function that will receive as a parameter the model (or mapped model) of the grid row and must return a string which will be used a value for the cell

GridModelBuilder

It is used to build the model of the grid by sorting, paging, grouping the items and building the model.
Mapdefines a function that maps the Model to a Dto, this way Column.Name will still be bound the the Model's properties but for cell values the values from the Dto will be used
Keydefines a property on which the data will be sorted when there's no sorting, this is needed when using Entity Framework because it does not allow paging if the data is not ordered at least by one column
MakeHeaderdefines a function for creating the GroupHeader
MakeFooterfunction for creating a group footer



Comments
By accessing this site, you agree to store cookies on your device and disclose information in accordance with our cookie policy and privacy policy .