BForms Grid and Toolbar components are designed to provide rich functionality, cross-browser, cross-device and internationalization support for tabular data providing full CRUD and search operations over complex datasets.

The feature set includes AJAX-enabled paging, sorting, editing, filtering and built-in data repository adapted for Entity Framework that can be customized with your own query logic. The UI is touch friendly and HTML5 enhanced featuring edit in place, master-details view and multi row select with bulk actions.

On the client side, the Grid is deployed as an AMD jQuery widget that supports theming and templates. The styling is done using bootstrap v3 CSS grid system.


Models

The first step of the grid creation is the model definition.

Row Model

public class ContributorRowModel : BsGridRowModel<ContributorDetailsReadonly> 
				/* : BsItemModel // simple rows - no details */
{
    public int Id { get; set; }

    [BsGridColumn(Width = 2, IsEditable = true)]
    public string Name { get; set; }

    public bool Enabled { get; set; }

    public Dictionary<string, object> RowData()
    {
        return new Dictionary<string, object> 
        {
            { "data-objid", Id },
            { "data-active", Enabled }
        };
    }
}

As you may have noticed in the above example, there are some unusual things declared in the row model. The RowData() method helps you define specific attributes in the row's html (data- attr), while the BsGridColumnAttribute allows you to set specific properties for each grid column.


BsGridColumnAttribute

Options

IsSortable

type bool
default true

Set the grid column as orderable.

IsEditable

type bool
default true

Set the grid column as inline editable.

Width

type int
default 0

Set the width of the column. Expected values: 1 - 12

Usage

type BsGridColumnUsage
default BsGridColumnUsage.Both

Set the scope of the property. Supported values: Excel / Html / Both


After you've defined the row model, wrap it up with the BsGridModel<TRow> and append it to the view model.

View Model

public class ContributorsViewModel
{
    [BsGrid(HasDetails = true, Theme = BsTheme.Blue)]
    [Display(Name = "Contributors", ResourceType = typeof(Resource))]
    public BsGridModel<ContributorRowModel> Grid { get; set; }
}


As you can see in the example, you can decorate the grid model with the BsGridAttribute. This allows you to set the color theme and specify whether the grid supports expandable rows.


BsGridAttribute

Options

HasDetails

type bool
default false

Flag for expandable rows.

Theme

type BsTheme
default BsTheme.Default (turqoise color)

Set the grid's theme.


Grid helper

In order to render a grid, use the Html.BsGridFor html helper extension.

@Html.BsGridFor(m => m.Grid)


This helper returns a BsGridHtmlBuilder used to build and configure the html of the grid. This way, you can set the grid's properties adding attributes, and columns.


BsGridHtmlBuilder

Methods

HtmlAttributes(Dictionary<string, object> htmlAttributes)

params:

  • htmlAttributes

    type Dictionary<string, object>
    default none
    description object representing a key-value set of html attributes

Set html attributes to the grid's dom element wrapper.

Example

@Html.BsGridFor(m => m.Grid)
     .HtmlAttributes(new { @class = "custom_class" })


Theme(BsTheme theme)

params:

  • theme

    type BsTheme
    default BsTheme.Default
    description theme selector

Set the grid's color theme.

Example

@Html.BsGridFor(m => m.Grid)
     .Theme(BsTheme.Orange)


GridResetButton()

Add a reset button.

Example

@Html.BsGridFor(m => m.Grid)
     .GridResetButton()

ConfigureRows(Action<BsGridRowConfigurator<TRow>> configurator)

params:

  • configurator

    type Action<BsGridRowConfigurator<TRow>>
    default none
    description rows configurator (html attributes, has details, color)

Using this method, you can add html attributes to each row, and set its color based on your row model. By default, the BsGridAttribute decides whether the rows have details (are expandable), but in some cases you may want some of your rows expandable and others not.

Example

@Html.BsGridFor(m => m.Grid)
     .ConfigureRows(cfg =>
     {
            cfg.HasDetails(row => row.Enabled ? true : false) // is expandable ?
               .HasCheckbox(row => row.Enabled ? true : false) // disable checkbox ?
               .HtmlAttributes(row => new Dictionary<string, object> { 
                   { "data-objid", row.Id }, 
                   { "data-active", row.Enabled } 
               })
               .Highlighter(row => row.Enabled ? "#59b444" : "#f0ad4e"); // row color
     })


ConfigureColumns(Action<BsGridColumnFactory<TRow>> configurator)

params:

  • configurator

    type Action<BsGridColumnFactory<TRow>>
    default none
    description columns factory (used to add and configure columns)

By default, the grid will be build based on the BsGridColumnAttribute existence on the row model's properties. It's actually all you have to do to add columns to the grid. But, just in case you want to use the row model as common model for different grids, you can add, remove or update specific columns using this method.

Example

@Html.BsGridFor(m => m.Grid)
     .ConfigureColumns(cols =>
     {
        cols.Add(c => c.Enabled)
            .Name(Resource.Enable) // column header 
            .SetWidth(3) // column width
            .Sortable() // is sortable?
            .Text(x => x.Enabled ? Resource.Yes : Resource.No); // text to display

        cols.For(c => c.Name) // edit specific column
            .Name(Resource.Name); // update the column header
     }


ConfigureBulkActions(Action<BsBulkActionsFactory> configurator)

params:

  • configurator

    type Action<BsBulkActionsFactory>
    default none
    description bulk actions factory (used to add and configure bulk actions and row selectors)

Using this method to configure the grid, will trigger the rendering of a set of buttons above it and a checkbox in each of its rows.
The buttons are used to apply certain actions to the selected rows.
The bulk actions selectors are helpers that are used to select rows that fulfill certain requirements.

You can choose from a set of predefined actions using BsBulkActionType enum and from a set of predefined selectors using BsBulkSelectorType enum.

Example

@Html.BsGridFor(m => m.Grid)
     .ConfigureBulkActions(bulk =>
     {
         bulk.AddAction(BsBulkActionType.Delete); // add predefined action
         bulk.AddAction() // add custom action
             .StyleClass("btn-success js-btn-enable_selected")
             .Title("Enable selected")
             .GlyphIcon(Glyphicon.Ok);

         bulk.AddSelector(BsBulkSelectorType.All); // add predefined rows selector
         bulk.AddSelector() // add custom rows selector
             .StyleClass("js-actives")
             .Text(@Resource.Enabled);

         bulk.ForSelector(BsBulkSelectorType.All) // update specific selector
             .Text(@Resource.All);
    })


PagerSettings(BsPagerSettings pagerSettings)

params:

  • pagerSettings

    type BsPagerSettings
    default none
    description pager settings (page size, template, show buttons, etc)

The method is used to configure the pagination settings of the grid. In this way, you can set the page size, use a specified partial view to render the pager, hide or show certain buttons.

Example

@Html.BsGridFor(m => m.Grid)
     .PagerSettings(new BsPagerSettings 
     {
        Size = 5
        ShowFirstLastButtons = true,
        ShowPrevNextButtons = true,
        HasPagesText = true,
        HasPageSizeSelector = true
     })


Repository

BsBaseGridRepository<TEntity, TRow>

Wanting to make your job easier, we created an abstract class to help you standardize the server side grid creation and also write less code.

Inheriting this base repository, you just have to implement a few methods and the rest is being handled for you.

The order of the operations is Get Query > Filter Query > Order Query > Map Query


The first step is to implement the Query() method. You can consider this method, as a way of getting the basic query, or the query used for the total items count.

IQueryable<TEntity> Query();

return type IQueryable<TEntity>

Example

public override IQueryable<Contributor> Query()
{
    var query = db.Contributors.AsQueryable();

    // filter query based on BsGridRepositorySettings<TSearch> Settings

    return query;
}

The next step will be implementing the OrderQuery() method. Here you will order your query using the orderedQueryBuilder property.

OrderQuery(IQueryable<TEntity> query);

return type IOrderedQueryable<TEntity>
params:

  • query

    type IQueryable<TEntity> query
    description return value of Query()

If the name of your model property is not the same as the name of the database column, you will need to use OrderQuery() as shown in the next example.

Example

public override IOrderedQueryable<Contributor> OrderQuery(IQueryable<Contributor> query)
{
    this.orderedQueryBuilder.OrderFor(x => x.Name, y => y.FirstName + " " + y.LastName);

    var ordered = this.orderedQueryBuilder.Order(query, x => x.StartDate, BsOrderType.Ascending);

    return ordered;
}

As you observe, your model has the property Name but the database has the columns FirstName and LastName, so you'll need to specify how it will be sorted.


The final step is implementing MapQuery() method. This method is used make the select and convert your entities in row models. To do this, you will most likely implement a mapper(TEntity, TRow) to use in the select.

MapQuery(IQueryable<TEntity> query);

return type IEnumerable<TRow>
params:

  • query

    type IQueryable<TEntity>
    description return value of OrderQuery()

Example

public override IEnumerable<ContributorRowModel> MapQuery(IQueryable<Contributor> query)
{
    return query.Select(MapContributor_ContributorRowModel);
}


I guess you're asking yourself, "what now?".

Well, now all you have to do is call the method ToBsGridViewModel() in the controller and there you have your grid model all "mapped out and ready to go".

Example

public ActionResult Index()
{
    var gridModel = _gridRepository.ToBsGridViewModel(
                       new BsGridRepositorySettings<ContributorSearchModel>
                       {
                          Page = 1,
                          PageSize = 5
                       });

    var model = new ContributorsViewModel
    {
        Grid = gridModel,
    };

    return View(model);
}


You can use the same method in different scopes (pagination ajax, add new row) to get the exact data you need (set of rows, single row).
Also, the repository allows you to override it, in case you want a custom implementation.


Javascript

Firstly, go ahead and require bforms.grid.js aka bforms-grid (defined in RequireJS.json).

require([
        'bforms-grid'    
], function () { }


Now that the script is loaded we can apply the grid widget on the element.

$('#grid').bsGrid({
    uniqueName: 'usersGrid',
    pagerUrl: this.options.pagerUrl   
});


For further configuration see the list of options below:


Options

uniqueName

type string
default DOM element id

Used to uniquely identify the grid. It is not required as long as the grid has the id attribute set.

pagerUrl

type string
default null

Represents the url used in pagination. After making an ajax request to that action, it expects to receive back the items count and the html.

rowActions

type array
default []

Represents a set of actions applicable on the specified item. The trigger buttons have to be in the details html container.

Example

rowActions: [{
    btnSelector: '.js-btn_state',
    url: this.options.enableDisableUrl,
    handler: function (e, options, $row, context) {},
}, {
    btnSelector: '.js-btn_delete',
    url: this.options.deleteUrl,
    init: function (options, $row, context) {},
    context: this
}]


filterButtons

type array
default []

Configure the grid's bulk action selectors.

Example

filterButtons: [{
    btnSelector: '.js-actives',
    filter: function ($el) {
        return $el.data('active') == true;
    }
}, {
    btnSelector: '.js-inactives',
    filter: function ($el) {
        return $el.data('active') != true;
    },
}],


gridActions

type array
default []

Configure the grid's bulk actions (actions that apply to the selected rows)

Example

gridActions: [{
    btnSelector: '.js-btn-exportExcel_selected',
    handler: function ($rows, context) {
        var data = {};
        var ids = [];
        $rows.each(function () {
            ids.push($(this).data('objid'));
        });
        data.ids = ids;
        data.settings = context.refreshModel;

        // do something with data
    }
}]


detailsUrl

type string
default null

Represents the url used to get the content of the row details.

beforeRowDetailsSuccess

type function
default null

Function triggered before the details ajax.

afterRowDetailsSuccess

type function
default null

Function triggered after the details ajax.

updateRowUrl

type string
default null

Represents the url used to get the content of a single row (with or without details).


CSS styling

Building the grid

The grid is made from 2 HTML parts:

Grid toolbar and Grid view. Your page can have more than one grid and a grid can have multiple Grid views. All of which is encapsulated in a Grid container.

The structure in our example looks like this:


How a grid item is formed

One grid row has two major HTML parts: header and details.

The header is the part that you’ll see when the items are collapsed. We made this by using the grid system provided by bootstrap, which we encapsulated in a <header> tag.

The grid row details is the one you’ll see after expanding one grid row. In our case this was build using two editable forms, two columns in total, but you can place your content on one or more columns if you like. At the end you’ll find the row controls buttons. They are not placed side by side to show an example of how you can differentiate actions not only through color but also through position. You can change this by removing the pull_right class from the second button.

At a closer look you will find, right before the <header> a <span> with a background color. This is used to highlight different rows in the grid. You can choose whatever colors suits your needs or you can remove it.