DataGrids are one of the most powerful, popular components in enterprise applications. Almost all of our customers use FlexGrid in their applications. Grids can be very complicated and are usually too cumbersome to develop on your own, which is why many people turn to FlexGrid (or other grid components) instead of rolling out their own. When you use FlexGrid, you can spend your time building an application instead of creating and maintaining a complex data grid.
When you use FlexGrid, you can spend your time building an application instead of creating and maintaining a complex data grid.
When selecting a JavaScript data grid, make sure you ask: how flexible and customizable is this grid? Naturally, different applications require vastly different grid implementations. Most grids are somewhat flexible, but FlexGrid is built to be (it's in the name, after all). Our philosophy with FlexGrid is to make the core grid very small and very fast... Then we make it extensible it can be customized to any need without bloating the core.
One of the most common ways to customize a grid is to create custom cells. Custom cells bring a grid’s data to life, making it more than just a data table. Here are some examples of custom cell rendering:
- Data formatting
- Custom content (images, sparklines, etc)
- Conditional formatting
- Calculated cells
- Custom actions (links, buttons, etc)
- Custom editors
- Complex cells (multiple elements)
- Dynamically updated cells
FlexGrid has many different ways to create custom cells.
- formatItem event
- CellTemplates (Angular)
- cellFactory (not common)
Let’s take a look at these different implementations in more detail.
Using the formatItem Event to Create Custom Cells
The formatItem event occurs when an element representing a cell has been created. This event can be used to format cells for display. This event is fire for all cells (including headers), not just data cells. So this event is very useful for formatting any cell in the entire grid.
The formatItem event provides a FormatItemEventArgs class as its arguments, which contains everything you need to customize the cell being rendered (and more).
Let’s take a look at a simple example of customizing cells using formatItem.
In this example, we will do some conditional formatting to change the color of the cell based on its value. This will be a visual indicator if sales are too low or high in the Sales column of our grid.
You can look through the boilerplate code in the sample, but let’s look at the formatItem event handler.
formatItem: function(s, e) {
//check if it is a data cell, then check to see if it is the 'sales' column
if (e.panel == s.cells && s.columns[e.col].binding == 'sales') {
//get the data item related to the row
var item = s.rows[e.row].dataItem;
//if the item.sales are below 1000, add a 'low' class, otherwise remove the class if it exists
wijmo.toggleClass(e.cell, 'low', item.sales < 1000);
//if the item.sales are above 5000, add a 'high' class, otherwise remove the class if it exists
wijmo.toggleClass(e.cell, 'high', item.sales > 5000);
}
}
A couple of interesting things about this code:
- We first make sure we are within the data cells panel using: e.panel == s.cells. This ensures we aren’t modifying header cells.
- We use the row’s data item to get the value for the cell.
- We use toggleClass to add or remove the indicator classes. This might seem strange, but the reason is that FlexGrid recycles cells with a rendering technique called virtualization. We only render what is needed for the screen to keep the DOM small and fast. But this means that if you modify a cell conditionally, you need to revert that change if the condition is not true. Otherwise, if a cell with an original value of 200 was colored red, and then recycled with a new value of 1200. The formatItem handler needs to make sure to remove that previously applied color. This is a common mistake we see, so it’s important to remember.
Now that you know the basics of formatItem, let’s look at some more complicated implementations.
Conditional Styling, Calculated Cells and Custom Icons
This sample extends the previous sample to add some calculated columns and custom icons on top of the conditional formatting.
Custom Content
This example adds custom controls into the cells to display sparklines and star ratings. These are just examples, and anything could be rendered inside each cell.
Custom Actions
This sample shows how to add buttons into cells that can perform custom actions. In this instance, the buttons actually change the row to edit mode when clicked. This shows how easy it is to change the editing behavior of the grid from its default (single-cell editing) behavior.
Read the formatItem documentation or explore more custom cell samples in Learn Wijmo.
Using Cell Templates in Angular applications
This section could (and will) be an article all on its own, but we'll take a quick look at it now. Cell Templates are something we added to our Angular, AngularJS and Knockout interops that enable you to declare cell templates in markup. This allows us to easily create custom cells in markup without having to use any event handlers.
Cell Templates are our favorite way of creating custom cells. Let’s take a look at an example to see why.
Cell Templates are our favorite way of creating custom cells.
In this simple Angular example, we'll add a button to a column. The beauty of this sample is that it's all done in Angular markup.
Here's the entire markup for the grid. You can see the second column uses a cell template, and the third column uses a cell edit template:
<wj-flex-grid [itemsSource]="data" style="height:300px">
<wj-flex-grid-column [header]="'Country'" [binding]="'country'"></wj-flex-grid-column>
<wj-flex-grid-column [header]="'Template'">
<ng-template wjFlexGridCellTemplate [cellType]="'Cell'" let-cell="cell">
<button class="btn btn-default" (click)="clickItem(cell.item.country)">
<img src="http://flagpedia.net/data/flags/mini/{{cell.item.abb}}.png"/>
Click Me!
</button>
</ng-template>
</wj-flex-grid-column>
<wj-flex-grid-column [header]="'Downloads'" [binding]="'downloads'" [format]="'n0'">
<ng-template wjFlexGridCellTemplate [cellType]="'CellEdit'" let-cell="cell">
<wj-input-number [(value)]="cell.value" [step]="1"></wj-input-number>
</ng-template>
</wj-flex-grid-column>
</wj-flex-grid>
Some interesting things about this sample:
- We add ng-template components inside a column to define a template.
- We can set the type of template by using the cellType property of the ng-template.
- In this example, we have a cell template for the Country column and a cell edit template for the Downloads column.
- Notice we can use Angular (click) bindings inside the template. This is a powerful feature since we can declare behavior inside the template.
- Also notice that the img tag uses binding syntax to create the src attribute, another powerful feature inside templates.
- Another thing we could use in templates is conditional formatting. We're able to use Angular “if” bindings as well.
- For the Downloads, we use an edit cell template and insert a Wijmo InputNumber control. Any custom components can be used inside templates.
- The cell edit template is only used when the cell goes into edit mode.
Angular Cell Template Tutorial
In this sample, you'll see the full power of our Angular Cell Templates. It uses all the different cell template types to customize every cell in the grid.
Using CellFactory to Take Over Rendering
Last, and certainly most difficult, is the CellFactory approach. You'd use this only if you need to completely take over how the grid renders every cell. We do not recommend this unless you really need it (and some do).
We aren’t going to go into the code for this implementation since it's so complicated. But rest easy knowing that if you really want to take over rendering the FlexGrid, you can do so. Look over the code in our CellFactory sample if you want to see how to follow this approach on your own.
Summary
Now you’ve seen the different ways to implement custom cells in FlexGrid: formatItem event, Angular Cell Templates and Cell Factory. We suggest using the formatItem event or Cell Templates if you're working with Angular. The samples above should help you get started on customizing your own FlexGrid.