The Kendo UI Grid is one of the most functional and elegant HTML5-based grid systems around. The Kendo UI Grid is used to easily allow users to visualize and interact with extremely large datasets- I have personally used Kendo Grids to convey over 60 million (60,00,000) records at a time using virtualization. The grids support paging, sorting, filtering, frozen columns, grouping, pivoting, etc, and allow for the editing of records. Grid data can also be exported to excel or pdf.

The grids are themeable and fully integrated with the other Kendo UI widgets and other Kendo UI widgets, such as Kendo dropdowns, can be embedded into a cell. The Kendo grids can be used natively with Angular, React, Vue and jQuery. Additionally, there are PHP and .Net wrappers, and Kendo UI can be easily used with ColdFusion as well. In this article we will show you how to use the grids with ColdFusion, however, like the rest of our articles, the client logic is written in JavaScript and jQuery and is server agnostic- you should be able to follow along.



Kendo Grid Demonstration

Please click on the button below to see the Kendo UI Grid that uses this code.


When Should You Use a Kendo UI Grid?

I use Kendo UI Grids every time I would typically use an HTML table to convey tabular data. The Kendo UI grids are interactive and offer a lot of improvements over a traditional HTML table, such as adding the ability to sort and group the data and will create a uniform look and feel when using a Kendo Theme. 


Kendo UI Grid Initializing and Binding Options

Kendo UI grids can be initialized using a simple HTML table or from a remote data service.

If the grids are initialized from a data service, the data can be bound to:

  1. Local JavaScript Data
  2. Remote Server Endpoint
  3. Kinvey Backend Services
  4. GraphQL Service
  5. SignalR
  6. WebSockets

In this series of articles, we will focus on binding the grids both locally and to a ColdFusion Service Endpoint.


CfBlogs Database Background

In the examples below, we will use ColdFusion to make a query to the cfblogs.org RSS blog aggregator database (formerly cfbloggers). The Cfblogs.org database collects data every 15 minutes from over 147 different ColdFusion blog sites and is updated whenever a new blog post is made and generates a tweet that summarizes the new blog post on Twitter.


Initializing a Grid from a Table

In the demonstration below, we will create a Kendo Grid from a static table showing the top ColdFusion-related blogs according to the number of posts made in the last calendar year.

In this example, we are querying the CfBlogs MySql database for active blogs, counting the number of blog posts in the last year, and getting the date of the last post. We are then looping through the query to create the data within the table cells. This code should be familiar to the ColdFusion developer.


SELECT	
		COUNT(e.posted) as count,
		MAX(date_format(e.posted, '%m/%d/%Y %r')) as maxDate,
		b.name as blog, 
		e.categories, 
		b.description as blogdescription, 
		b.url as blogurl,
		b.blogsoftware
	FROM	entries e, blogs b
	WHERE	e.blogidfk = b.id
	AND b.active = 1
	AND e.title is not null
	AND  e.posted > now() - INTERVAL 12 month
	GROUP BY blog
	ORDER BY count DESC
</cfquery>

<table id="grid">
	<colgroup>
		<col style="width:10%" />
		<col style="width:25%" />
		<col style="width:50%" />
		<col style="width:15%" />
	</colgroup>
	<thead>
		<tr>
			<th data-field="count"># Posts</th>
			<th data-field="blog">Blog</th>
			<th data-field="blogdescription">Description</th>
			<th data-field="maxDate">Last Post</th>
		</tr>
	</thead>
	<tbody>
	<cfoutput query="Data">
		<tr>
			<td>#count#</td>
			<td><a href="#blogurl#" target="new">#blog#</a></td>
			<td>#blogdescription#</td>
			<td>#maxDate#</td>
		</tr>
	</cfoutput>
	</tbody>
</table>

After generating the table, we simply initialize the Kendo UI Grid using a few lines of Javascript.

We are specifying the id of the table, grid, to initialize the grid. There are a few additional optional arguments that we will use to make this grid sortable.

The sortable argument makes the Kendo UI grid, well you guessed it- sortable, and the columnMenu argument places a menu at the top of the grid. The columMenu argument takes multiple additional arguments, and here we want to set filterable to false as we are binding the data to an HTML table.

These methods will be covered in more detail in future blog posts.


<script>
	$(document).ready(function() {
		$("#grid").kendoGrid({
		sortable: true,
		columnMenu: {
			filterable: false
		}
		});
	});
</script>


Initializing a Kendo UI Grid Using a ColdFusion Remote Server Endpoint


Server Side Code Using ColdFusion

The following function is in the Demo.cfc ColdFusion Component. You don't need to use a ColdFusion component as the service endpoint, you can use any ColdFusion template, however, it is useful to use a component with multiple methods for a variety of reasons. Namely, ColdFusion components use an object-oriented approach, they are generally faster than a UDF, and they are generally more secure and extensible.

This function is no different than the server-side functions that we used for the Kendo dropdowns in previous articles. We are simply querying the database and transforming the ColdFusion query object into JSON using our CfJson method and returning the JSON string. You should note that we are also using returnFormat="json"  in the function declaration.


<cffunction name="getLastYearTopBlogsForGrid" access="remote" returnformat="json" output="false" 
		hint="Returns the most active ColdFusion blogs by most recent date for the last calendar year">
	<!--- There are no arguments for this function. --->
	<cfsetting enablecfoutputonly="true" />

	<cfset dsn = "cfbloggers">

	<cfquery name="Data" datasource="#dsn#">
		SELECT	
			COUNT(e.posted) as count,
			MAX(date_format(e.posted, '%m/%d/%Y %r')) as maxDate,
			b.name as blog, 
			e.categories, 
			b.description as blogdescription, 
			b.url as blogurl,
			b.blogsoftware
		FROM	entries e, blogs b
		WHERE	e.blogidfk = b.id
		AND b.active = 1
		AND e.title is not null
		AND  e.posted > now() - INTERVAL 12 month
		GROUP BY blog
		ORDER BY count DESC
	</cfquery>

	<!--- Using my jsonArray.cfc --->
	<!--- Convert the query object into JSON using the convertCfQuery2JsonStruct method --->
	<cfinvoke component="#jsonArray#" method="convertCfQuery2JsonStruct" returnvariable="jsonString">
		<cfinvokeargument name="queryObj" value="#Data#">
		<cfinvokeargument name="includeTotal" value="false">	
	</cfinvoke>

	<cfreturn jsonString>
</cffunction>

The JSON String Returned by the ColdFusion Endpoint

The ColdFusion server endpoint returns the following JSON. Note: I formatted the JSON and have only included the first 5 records for brevity.

[{
	"maxDate": "12/31/2021 01:46:00 AM",
	"total": 30,
	"blogsoftware": "http://wordpress.org/?v=2.9.2",
	"count": 206,
	"blogurl": "https://www.bennadel.com
",
	"id": 134,
	"blogdescription": "Ben Nadel's web development blog on ColdFusion, jQuery, HTML5, AJAX, SQL, and all aspects of web application development.",
	"blog": "Ben Nadel",
	"categories": "ColdFusion"
}, {
	"maxDate": "11/08/2021 10:51:00 PM",
	"total": 30,
	"blogsoftware": "FeedGenerator",
	"count": 124,
	"blogurl": "https://www.intothebox.org
",
	"id": 144,
	"blogdescription": "ContentBox",
	"blog": "ContentBox",
	"categories": "News, Schedule, Speakers"
}, {
	"maxDate": "12/17/2021 11:29:11 AM",
	"total": 30,
	"blogsoftware": "https://wordpress.org/?v=5.6.1",
	"count": 111,
	"blogurl": "https://coldfusion.adobe.com
",
	"id": 104,
	"blogdescription": "Connect with community",
	"blog": "ColdFusion",
	"categories": "Announcements,Blog,Online ColdFusion Meetup,announcements,blog,ColdFusion,online coldfusion meetup"
}, {
	"maxDate": "11/13/2021 06:00:00 PM",
	"total": 30,
	"blogsoftware": "Eleventy",
	"count": 77,
	"blogurl": "https://www.raymondcamden.com
",
	"id": 152,
	"blogdescription": "DevRel at large, Star Wars nerd, Web/Serverless hacker, lover of good beer and good books. Oh, and cats.",
	"blog": "Raymond Camden",
	"categories": "eleventy,static sites"
}, {
	"maxDate": "10/20/2022 04:45:00 PM",
	"total": 30,
	"blogsoftware": "Galaxie Blog",
	"count": 74,
	"blogurl": "https://www.gregoryalexander.com/blog/",
	"id": 1,
	"blogdescription": "A technical blog powered by Galaxie Blog - the most beautiful and functional open source ColdFusion/Kendo UI based blog in the world.",
	"blog": "Gregory's Blog",
	"categories": "Galaxie Blog"
}]

Inspect the JSON Yourself Using the Browsers Inspector

For debugging purposes, you often will want to inspect the JSON yourself using the browser's developer tools

All of the major browsers have some type of developer console to inspect the web page elements and browser traffic. If you're using Chrome, launch the DevTools console by pressing the F12 button, or if you're on a Mac, press the function and F12 key at the same time. 

Once the DevTools inspector is open, click on the network tab, and refresh the Kendo window and you should see a link to the Demo.cfc?method=topBlogsByPostsForCalendarYear in the list to the right. Click on it to see the JSON string returned from the server. For more information on the inspector, please refer to your browser's documentation.



The Kendo DataSource

The following Kendo DataSource invokes the topBlogsByPostsForCalendarYear function in the Demo.cfc ColdFusion component that we covered above. There is nothing different than the data source logic that we used in previous articles, however, in future Kendo Grid-related articles, we will identify the datatype inside the data source for advanced grid handling.

var topBlogsByPostsDs = new kendo.data.DataSource({
	// Determines which method and cfc to get and set data.
	transport: {
		read: {
			url: "<cfoutput>#application.baseUrl#</cfoutput>/demo/Demo.cfc?method=topBlogsByPostsForCalendarYear", // the cfc component which processes the query and returns a json string.
			dataType: "json", // Use json if the template is on the current server. If not, use jsonp for cross domain reads.
			method: "post" // Note: when the method is set to "get", the query will be cached by default. This is not ideal.
		}//read:
	},//transport:
	cache: false
});//topBlogsByPostsDs = new kendo.data.DataSource

Initializing the Kendo UI Grid

The script to initialize the grid inserts the grid widget into the grid div in the client-side code.

We are using the topBlogsByPostsDs data source and setting the basic grid options to allow sorting and allowing the user to search the grid for data using filterable: true. We will cover the column menu arguments in later articles.

Arguments in the columns array are optional, you can omit them, however, the grid will render all of the columns with equal widths and the column title will be the name of the database column which is not ideal.

The columns array should always be used with the Kendo UI grid in order to specify the column title, whether you want the column to have search filters, and to set the column widths. 

Here we are applying the column database name to the field, setting the title of the column, specifying whether the column filter menus are available, and set the column widths. The width argument can be a numeric value if you want to set a pixel width, or as a string, if you want to use percents.

var topBlogsByPosts = $("#grid").kendoGrid({
	dataSource: topBlogsByPostsDs,
	sortable: true,
    columnMenu: {
        filterable: false
    },
    // Column properties
    columns: [{
        field:"count",
        title: "# Posts",
        filterable: true,
        width:"15%"
    }, {
        field:"blog",
        title: "Blog",
        filterable: true,
        width:"20%"
    }, {
        field:"blogdescription",
        title: "Description",
        filterable: true,
        width:"50%"
    }, {
        field:"blogurl",
        title: "URL",
        filterable: true,
        width:"20%"
    }]// columns:
});// var topBlogsByPosts = $("#grid").kendoGrid

Client Side Code

The client-side code should be self-explanatory- the only thing of note here is that we are placing a div with the id of grid that is used to contain the Kendo grid.

<h2>Most active ColdFusion blogs in the last year</h2>
<p>Based upon the number of posts made within the last year according to <a href="www.cfblogs.org">CfBlogs.org</a></p>

<!--- Empty iv container for the grid. --->
<div id="grid"></div>

We will be covering more advanced Kendo UI Grid examples in future articles.

Thanks for reading!

Further Reading