| Quick Start Guide | |
|---|---|
| What You Will Need |
|
| Controls Referenced | |
| Tutorial Concept | Master advanced JavaScript datagrid template techniques and build interactive cell templates featuring buttons, links, images, ratings, sparklines, and conditional formatting for enterprise-grade user experiences. |
As more software that would traditionally be built as desktop applications is built as web applications, the controls developers need in a web environment have become more advanced to meet these needs. Users need interactive interfaces where controls, such as data grids, expand beyond static tables. Whether you're building dashboards, CRM systems, financial tools, or business applications, the ability to customize cells with buttons, hyperlinks, images, and more can dramatically improve usability and user engagement.
Fortunately, Wijmo's JavaScript data grid, FlexGrid, makes advanced cell customization straightforward through its CellTemplates and CellMaker utility. In this article, we'll explore how to convert standard grid cells into dynamic UI elements that enhance both functionality and visual clarity.
By the end of this article, you'll know how to:
- Create interactive button columns
- Add hyperlinks and image cells
- Display star ratings and sparklines
- Apply conditional formatting to cells
- Build polished, enterprise-grade data grid experiences
Ready to check it out? Download Wijmo Today!
How Cell Templates Help Users Read Data
Most data grids look similar by default, with rows of text values displayed in plain cells (a very straightforward design). While functional, this approach can become difficult to scan and interact with as datasets become larger.
Custom cell templates allow developers to solve several problems for users, such as:
- Improving readability by visualizing data
- Reducing clicks by embedding actions directly in the grid
- Helping users identify trends in the data more easily
- Creating a more intuitive user experience
Several examples of this include:
- Sales performance metrics displayed in a sparkline control
- Displaying product images directly in a row
- Status values shown as color-coded badges
- Actions appearing as embedded buttons
These enhancements turn FlexGrid into an interactive application interface instead of merely a passive data viewer.
Setting Up FlexGrid in Your Application
Before we start building customized cells, we need to create a FlexGrid instance in our JavaScript application. We'll be adding this to our Vite-scaffolded application, but we'll need to install Wijmo first. To do so, run the following command:
npm install @mescius/wijmo.all
Now, inside the markup, add an element to which we can bind the FlexGrid:
<div id="dataGrid"></div>
Next, import the required packages and CSS files that are needed to implement the FlexGrid:
import * as wjCore from '@mescius/wijmo';
import * as wjGrid from '@mescius/wijmo.grid';
import '@mescius/wijmo.styles/wijmo.css';
With all of that complete, the FlexGrid is ready to be implemented. However, we will need some data to display, so let's set up some mock data:
const data = [
{
id: 1,
product: 'Laptop',
sales: 120000,
rating: 4,
website: 'https://en.wikipedia.org/wiki/Laptop',
image: 'https://upload.wikimedia.org/wikipedia/commons/9/90/ThinkPad_X220.jpg',
trend: [15,10,12,18,22]
}, {
id: 2,
product: 'Monitor',
sales: 85000,
rating: 5,
website: 'https://en.wikipedia.org/wiki/Computer_monitor',
image: 'https://upload.wikimedia.org/wikipedia/commons/8/83/LG_Flatron_W2420R_%281%29.jpg',
trend: [5,8,12,10,14]
}, {
id: 3,
product: 'Keyboard',
sales: 42500,
rating: 4,
website: 'https://en.wikipedia.org/wiki/Computer_keyboard',
image: 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/LenovoKeyboard.jpg/1920px-LenovoKeyboard.jpg',
trend: [7,5,9,3,6]
}, {
id: 4,
product: 'Mouse',
sales: 58000,
rating: 3,
website: 'https://en.wikipedia.org/wiki/Computer_mouse',
image: 'https://upload.wikimedia.org/wikipedia/commons/2/22/3-Tasten-Maus_Microsoft.jpg',
trend: [3,7,5,9,7]
}
];
Finally, add the code required to implement the FlexGrid and bind our mock data to the data grid:
const grid = new wjGrid.FlexGrid('#dataGrid', {
autoGenerateColumns: false,
columns: [
{ binding: 'product', header: 'Product' },
{ binding: 'sales', header: 'Sales' }
],
itemsSource: data
});
This creates a simple FlexGrid control that displays two columns of data: Product and Sales. Now, if we run the application, we should see the following in our browser:

This gives us a simple starting point. Now, let's begin enhancing the cells.
Creating Interactive Button Columns
One of the most common requirements when building a data grid is to embed actions directly in rows. Instead of requiring users to select a row and navigate elsewhere, you can place action buttons directly in the grid's cells. Wijmo provides a convenient CellMaker.makeButton() method for this purpose.
To add buttons to the FlexGrid, first, we need to import Wijmo's CellMaker class:
import {CellMaker} from '@mescius/wijmo.grid.cellmaker';
Now, we can update the FlexGrid's columns array to include a new column that utilizes buttons:
const grid = new wjGrid.FlexGrid('#dataGrid', {
autoGenerateColumns: false,
columns: [
{
binding: 'id',
header: 'Actions',
width: 100,
cellTemplate: CellMaker.makeButton({
click: (e, ctx) => {
alert(`Viewing ${ctx.item.product}`);
}
})
},
{ binding: 'product', header: 'Product', width: '*' },
{ binding: 'sales', header: 'Sales', width: '*' }
],
itemsSource: data
});
This implementation will add a new column using the id property, which will use the CellMaker class we just imported to turn the cells in this column into buttons. When we run the application, the updated grid should appear like so:

When we click on one of the buttons, we'll see an alert that contains the product name of the row that we interacted with:

Adding Hyperlink Columns
There will be times when you need to link to other URLs from a data table; maybe the user needs to access a different web page to see more information about the data row, or you want them to be able to access a product page by clicking the URL. Whatever the reason, displaying URLs as raw text isn't ideal. Hyperlink templates make grids look more intuitive and professional.
With the CellMaker class that we imported for using buttons, we can use the CellMaker.makeLink() method to add a column that contains a hyperlink template to display the data's URLs:
const grid = new wjGrid.FlexGrid('#dataGrid', {
autoGenerateColumns: false,
columns: [
{
binding: 'id',
header: 'Actions',
width: 100,
cellTemplate: CellMaker.makeButton({
click: (e, ctx) => {
alert(`Viewing ${ctx.item.product}`);
}
})
},
{ binding: 'product', header: 'Product', width: '*' },
{ binding: 'sales', header: 'Sales', width: '*' },
{
binding: 'website',
header: 'Product Link',
width: '*',
cellTemplate: CellMaker.makeLink({
text: '${item.product} Page',
href: '${item.website}',
attributes: {
target: '_blank',
rel: 'noopener noreferrer',
tabIndex: -1
}
})
}
],
itemsSource: data
});
Now, when we run the application, we'll see the updated FlexGrid, including the hyperlinks that we've just added:

These links are all active, and if a user clicks one, they'll be taken to the URL associated with the row's data object. Now, rather than having to copy and paste a URL or trying to discern where it takes the user, developers can easily set up hyperlinks within the FlexGrid.
Displaying Images Inside Grid Cells
Many times, especially in data grids where products are displayed, images are included in the data to give users an idea of what the product looks like. It's an excellent way for designers to improve readability and the user's visual scanning.
Like before, we'll use the CellMaker class (if you're noticing a pattern here, the CellMaker class is a very powerful class to allow you to customize cells within the FlexGrid) to call the makeImage() method and insert an image into the data grid:
const grid = new wjGrid.FlexGrid('#dataGrid', {
autoGenerateColumns: false,
columns: [
{
binding: 'id',
header: 'Actions',
width: 100,
cellTemplate: CellMaker.makeButton({
click: (e, ctx) => {
alert(`Viewing ${ctx.item.product}`);
}
})
},
{ binding: 'product', header: 'Product', width: '*' },
{ binding: 'sales', header: 'Sales', width: '*' },
{
binding: 'website',
header: 'Product Link',
width: '*',
cellTemplate: CellMaker.makeLink({
text: '${item.product} Page',
href: '${item.website}',
attributes: {
target: '_blank',
rel: 'noopener noreferrer',
tabIndex: -1
}
})
}, {
binding: 'image',
header: 'Images',
cssClass: 'cell-img',
width: '*',
cellTemplate: CellMaker.makeImage({
label: 'Image for ${item.product}'
})
}
],
itemsSource: data
});
If you noticed, there's an additional property on this column that we didn't use on the others: cssClass. Wijmo allows you to add custom CSS to specific rows, columns, and cells, which is what we'll do here.
If we open up the styles.css file, we'll add that class in with some custom styling to center the image in the cell:
.wj-flexgrid .wj-cell.cell-img {
padding: 0;
text-align: center;
}
Now, the FlexGrid will display our new column, including the images that we've added via the CellMaker class:

Creating a Star Ratings Column
Ratings can be difficult to scan when displayed as numeric values. Visual star ratings can communicate this information much more efficiently. In our case, we'll display each product's ratings in our data grid.
This time, we'll use the CellMaker class's makeRatings() method to convert our numeric value into a star ratings image:
const grid = new wjGrid.FlexGrid('#dataGrid', {
autoGenerateColumns: false,
columns: [
{
binding: 'id',
header: 'Actions',
width: 100,
cellTemplate: CellMaker.makeButton({
click: (e, ctx) => {
alert(`Viewing ${ctx.item.product}`);
}
})
},
{ binding: 'product', header: 'Product', width: '*' },
{ binding: 'sales', header: 'Sales', width: '*' },
{
binding: 'website',
header: 'Product Link',
width: '*',
cellTemplate: CellMaker.makeLink({
text: '${item.product} Page',
href: '${item.website}',
attributes: {
target: '_blank',
rel: 'noopener noreferrer',
tabIndex: -1
}
})
}, {
binding: 'image',
header: 'Images',
cssClass: 'cell-img',
width: '*',
cellTemplate: CellMaker.makeImage({
label: 'Image for ${item.product}'
})
}, {
binding: 'rating',
header: 'Product Rating',
width: 200,
align: 'center',
cellTemplate: CellMaker.makeRating({
range: [0, 5],
label: 'Product Rating'
})
}
],
itemsSource: data
});
Now, when we run the application, we'll see our ratings column displayed within the FlexGrid:

Visualizing Trends with Sparklines
There are times when your data includes trends that users need to interpret quickly. Sparklines make it easy for developers to embed mini-charts directly in cells. For our example, we'll embed a sparkline in our data grid to display the trendline for each product. Once again, we'll use the CellMaker class and its makeSparkline() method to implement this feature:
const grid = new wjGrid.FlexGrid('#dataGrid', {
autoGenerateColumns: false,
columns: [
{
binding: 'id',
header: 'Actions',
width: 100,
cellTemplate: CellMaker.makeButton({
click: (e, ctx) => {
alert(`Viewing ${ctx.item.product}`);
}
})
},
{ binding: 'product', header: 'Product', width: '*' },
{ binding: 'sales', header: 'Sales', width: '*' },
{
binding: 'website',
header: 'Product Link',
width: '*',
cellTemplate: CellMaker.makeLink({
text: '${item.product} Page',
href: '${item.website}',
attributes: {
target: '_blank',
rel: 'noopener noreferrer',
tabIndex: -1
}
})
}, {
binding: 'image',
header: 'Images',
cssClass: 'cell-img',
width: '*',
cellTemplate: CellMaker.makeImage({
label: 'Image for ${item.product}'
})
}, {
binding: 'rating',
header: 'Product Rating',
width: 200,
align: 'center',
cellTemplate: CellMaker.makeRating({
range: [0, 5],
label: 'Product Rating'
})
}, {
binding: 'trend',
header: 'Trendline',
width: 150,
cellTemplate: CellMaker.makeSparkline({
markers: SparklineMarkers.High | SparklineMarkers.Low,
label: '${item.product} sales trendline'
})
}
],
itemsSource: data
});
The sparkline we're creating here is just a simple line graph, but Wijmo's FlexGrid also allows you to make column graphs, as well as combine line and column graphs. We're also including a markers property that marks the high and low points of the sparkline.
Now, when we run the application, we'll see the new column displaying the product trend data in the FlexGrid control:

Applying Conditional Styling to Cells
The last feature we'll cover in this blog is setting conditional formatting on cells. Conditional formatting is one of the most impactful ways to improve data readability. Instead of making users interpret raw values manually, the data grid can use visual elements to emphasize important information.
To do this with Wijmo's FlexGrid, we'll use the formatItem event:
grid.formatItem.addHandler((s, e) => {
if(e.panel === s.cells) {
const col = s.columns[e.col];
if(col.binding === 'sales') {
const value = s.getCellData(e.row, e.col);
if(value > 100000) {
e.cell.style.backgroundColor = '#dff0d8';
e.cell.style.color = '#118013';
e.cell.style.fontWeight = 'bold';
} else if (value < 50000) {
e.cell.style.backgroundColor = '#dff0d8';
e.cell.style.color = '#d60e0e';
e.cell.style.fontWeight = 'bold';
}
}
}
});
What we're doing here is ensuring the item being formatted is part of the Sales column. If it is, we check whether the value is over 100,000 or under 50,000; if either condition is met, we'll apply some styling to the cell.
When we run the application, the data grid will display our conditionally-styled cells:

Conclusion
Advanced cell templates allow you to transform Wijmo's FlexGrid from a simple data table into a rich, interactive application surface. With only a minimal amount of code, you can create:
- Interactive workflows
- Visual analytics
- Embedded actions
- Rich data visualizations
- Enterprise interfaces
Wijmo's CellMaker utilities simplify much of this work, but that's not the only way Wijmo lets you customize the contents of your data grid cells. Developers can also insert their own custom components into cell templates. For more information, check out this Cell Templates demo.
Whether you're building dashboards, portals, analytics platforms, or financial systems, advanced cell customization can dramatically improve both usability and productivity.
If you'd like to learn more about FlexGrid's cell customization, check out Wijmo's CellMaker documentation.
Ready to try it out? Download Wijmo Today!
Happy coding!