Question

I'm trying to display a friendly message (like "No records found, try again later") within the grid content, when there are no records in the database.

From what I've seen in the docs, there is currently no way of doing this for the grid content. It's only doable for the footer. You can see the example in this fiddle: http://jsfiddle.net/lav911/uNWXJ/

I've purposely misspelled the data route, in order to have an empty grid. To see it with content, simply comment / uncomment these lines:

transport: {
            // read: "http://demos.telerik.com/kendo-ui/service/Northwind.svc/Customers"
            read: "http://demos.telerik.com/kendo-ui/service/Northwind.svc/Customerss"
        },

Is there a clean way of achieving this ?

Was it helpful?

Solution

Good news- this option is available now:

https://docs.telerik.com/kendo-ui/api/javascript/ui/grid/configuration/norecords#noRecords

you can set message via kendo template:

noRecords: {
    template: "No data available on current page. Current page is: #=this.dataSource.page()#"
}

or via message option:

noRecords: true,
messages: {
    noRecords: "There is no data on current page"
}

default text is "No records available." when set noRecords: true only

OTHER TIPS

You may use CSS: DEMO

tbody:empty:before {
    content:'NO DATA';
}

with litlle style :

tbody:empty:before {
    content:'NO DATA';
    display:table-cell;
    padding:0.5em;
}

I use the following when defining the grid:

$('#grid').kendoGrid({
    dataSource: employeeDataSource,
    dataBound: function () {
        DisplayNoResultsFound($('#grid'));
},


The javascript function 'DisplayNoResultsFound' is defines as follows:

function DisplayNoResultsFound(grid) {
    // Get the number of Columns in the grid
    var dataSource = grid.data("kendoGrid").dataSource;
    var colCount = grid.find('.k-grid-header colgroup > col').length;

    // If there are no results place an indicator row
    if (dataSource._view.length == 0) {
        grid.find('.k-grid-content tbody')
            .append('<tr class="kendo-data-row"><td colspan="' + colCount + '" style="text-align:center"><b>No Results Found!</b></td></tr>');
    }

    // Get visible row count
    var rowCount = grid.find('.k-grid-content tbody tr').length;

    // If the row count is less that the page size add in the number of missing rows
    if (rowCount < dataSource._take) {
        var addRows = dataSource._take - rowCount;
        for (var i = 0; i < addRows; i++) {
            grid.find('.k-grid-content tbody').append('<tr class="kendo-data-row"><td>&nbsp;</td></tr>');
        }
    }
}

A running demo can be found here

Firstly, you cannot fake an empty datasource just by giving an incorrect read url. This will just cause a read error and will never trigger any update on your grid's datasource, (ie. dataBound event will never happen). On the other hand, an empty datasource is still a valid datasource and will trigger the dataBound event.


Anyways, here is my solution. Firstly, to emulate an empty datasource, I have set the datasource like so:

    dataSource: []

Now, the proper way to check whether your grid is truly empty is to read the datasource itself. The others do it... in a more hacky way by reading html DOM. Please do NOT do this as you may have multiple pages, filters, etc... where the item is in the dataSource but not the DOM. Here is how you should do it:

if($("#grid").data("kendoGrid").dataSource.data().length===0){
    //do your stuff!
}

Now, when you read your datasource, the dataBound event is triggered every time. Thus, you should put the above code in the dataBound event. Check if grid dataSource is empty, and then fire a message to the user. Here is my full code for dataBound.

dataBound: function (e) {
    var grid = $("#grid").data("kendoGrid");
    var mBox = $("#msgBox");
    if (grid.dataSource.data().length === 0) {
        if (!mBox.data("kendoWindow")) {
            mBox.kendoWindow({
                actions: ["Close"],
                animation: {
                    open: {
                        effects: "fade:in",
                        duration: 500
                    },
                    close: {
                        effects: "fade:out",
                        duration: 500
                    }
                },
                modal: true,
                resizable: false,
                title: "No items",
                width: 400
            }).data("kendoWindow").content("<p>No contacts available. Please try again later.</p>").center().open();
        } else {
            mBox.data("kendoWindow").content("<p>No contacts available. Please try again later.</p>").open();
        }

    }
}

What is this crazy mess above? You'll notice that I am doing a lot of stuff with the variable mBox. This is simply an empty <div> I added on the html page with id msgBox, and I am using it to instantiate a kendoWindow to create the popup saying that there is no data.

You can find out more about kendoWindow here. So instead of using ugly alert boxes, I am just taking advantage of another part of kendo UI's widget library, which is customizable and controllable.

The if and else logic with the mBox simply handles subsequent calls to show the message. The first time, the kendoWindow has not been instantiated so it goes through the if clause. Subsequent calls with just reopen the window.

Give it a try :). You can click the next page buttons to verify that it will show the popup again. Here is a jsFiddle Demo.

enter image description here

 // Kendo Grid
         dataSource: dataSource,
         dataBound:gridDataBound,



//No data in the grid show message
        function gridDataBound(e) {
            var grid = e.sender;
            if (grid.dataSource.total() == 0) {
                var colCount = grid.columns.length;
                $(e.sender.wrapper)
                    .find('tbody')
                    .append('<tr class="kendo-data-row"><td colspan="' + colCount + '" class="no-data">There is no data to show in the grid.</td></tr>');
            }
        };

I know I'm late to the party but here's how I just did it. It's mostly copied from the TreeList's no data feature (I was annoyed that you didn't have the same thing with the standard grid). I made it into a prototype extension so it's automatically added to every grid. An option could also be added to make the message configurable.

// Replace the grid content with a status message (Can be reused for data errors if you want to show "Request failed [Reload]" or something like that.
kendo.ui.Grid.prototype._showStatus = function (message) {
    var status = this.content.find(".k-status");

    if (!status.length) {
        status = $("<div class='k-status' />").appendTo(this.content.closest(".k-grid-content"));
    }

    status.html(message);
};

// Put back the grid content instead of the status message
kendo.ui.Grid.prototype._hideStatus = function () {
    this.content.find(".k-status").remove();
};

// Keep the original render function so we can call it int our override
kendo.ui.Grid.prototype.__renderContent = kendo.ui.Grid.prototype._renderContent;

// Override the render function
kendo.ui.Grid.prototype._renderContent = function (data, colspan, groups) {
    this.__renderContent(data, colspan, groups);
    if (data.length)
        this._hideStatus();
    else
        this._showStatus("No data."); // Could also add an option for that text so you can choose the message in a grid config
};

On Grid Data Bound..

Add the following script to show Message.

 //ondatabound on user assginment grid grid
    function onUserAssignGridDataBound(e) {

        //Get the number of Columns in the grid
        var colCount = $("#UserAssignGrid").find('.k-grid-header colgroup > col').length;

        //If There are no results place an indicator row
        if ($("#UserAssignGrid").data("kendoGrid").dataSource._view.length == 0) {
            $("#UserAssignGrid").find('.k-grid-content tbody')
                .append('<tr class="kendo-data-row"><td colspan="' +
                    colCount +
                    '" style="text-align:center; padding-top:10px;background-color:#AFE4FA"><b>No Results Found!</b></td></tr>');

        }

Can't you do something like this -

if(this.tbody.rows.length === 0) {
     alert('no records');
     return;
}

Or you are looking for something even cleaner something inbuilt in Kendo? I think, this is an issue still there in Kendo UI which hasn't been fixed yet See this - http://www.telerik.com/forums/empty-grid-norecords-template

If your grid has detail grids (nested grids) then the above examples wont work on the nested grids. To ensure you apply this to all of your kendo grids you can do the following:

function kendoEmptyGridFix() {
    $("[data-role='grid']").each(function() {
        $(this).data("kendoGrid").bind('detailInit', function(e) {
            kendoEmptyGridFix();
        });
        $(this).data("kendoGrid").bind('dataBound', function(e) {
            var colCount = this.table.find("tHead tr th").length;
            if ($(this)[0].dataSource._view.length == 0) {
                var msg = ($(this)[0].dataSource.options.emptyMsg == undefined ? "No Results Found!" : $(this)[0].dataSource.options.emptyMsg);
                this.table.find('tbody').html('<tr class="kendo-data-row"><td colspan="' + colCount + '" style="text-align:center; padding-top:20px; padding-bottom:20px;"><div class="k-empty-grid-row">' + msg + '</div></td></tr>');

                // optional to hide pager section
                this.table.parent().find('.k-grid-pager').hide();
            };
        });
    });
}

Then call this function after all of your content has been loaded, there is no need to add it to each grid individually.

$(document).ready(function () {
    kendoEmptyGridFix();
});

if you wanted to change the message then add emptyMsg to your dataSource i.e.

dataSource: {
    transport: {
        read: {
            url: "/getItems/" + e.data.id,
            dataType: "xml"
        }
    },
    emptyMsg: 'There are currently no items available', 
    schema: {
        type: "xml",
        data: "/a/b",
        model: {
            fields: {
                "id": "id/text()",
                "status": "status/text()"
            }
        }
    },
    pageSize: 20
}

Kendo grid No Data found message

function gridDataBound(e) {
var grid = e.sender;
if (grid.dataSource.total() == 0) {
    var colCount = grid.columns.length;
    $(e.sender.wrapper)
        .find('tbody')
        .append('<tr class="kendo-data-row"><td colspan="' + colCount + '" class="no-data">Sorry, no data :(</td></tr>');
}

};

Not sure what was the exact version this question was asked, but in my case none of the above solutions worked.

I used the following one:

config : {
     noRecords: {
          message: "No records found."
     },
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top