Reloading/refreshing Kendo Grid - kendo-ui

How to reload or refresh a Kendo Grid using Javascript?
It is often required to reload or refresh a grid after sometime or after a user action.

You can use
$('#GridName').data('kendoGrid').dataSource.read(); <!-- first reload data source -->
$('#GridName').data('kendoGrid').refresh(); <!-- refresh current UI -->

I never do refresh.
$('#GridName').data('kendoGrid').dataSource.read();
alone works for me all the time.

In a recent project, I had to update the Kendo UI Grid based on some calls, that were happening on some dropdown selects. Here is what I ended up using:
$.ajax({
url: '/api/....',
data: { myIDSArray: javascriptArrayOfIDs },
traditional: true,
success: function(result) {
searchResults = result;
}
}).done(function() {
var dataSource = new kendo.data.DataSource({ data: searchResults });
var grid = $('#myKendoGrid').data("kendoGrid");
dataSource.read();
grid.setDataSource(dataSource);
});
Hopefully this will save you some time.

$('#GridName').data('kendoGrid').dataSource.read();
$('#GridName').data('kendoGrid').refresh();

Not a single one of these answers gets the fact that read returns a promise, which means you can wait for the data to load before calling refresh.
$('#GridId').data('kendoGrid').dataSource.read().then(function() {
$('#GridId').data('kendoGrid').refresh();
});
This is unnecessary if your data grab is instant/synchronous, but more than likely it's coming from an endpoint that won't return immediately.

If you do not want to have a reference to the grid in the handler, you can use this code:
$(".k-pager-refresh").trigger('click');
This will refresh the grid, if there is a refresh button.
The button can be enabled like so:
[MVC GRID DECLARATION].Pageable(p=> p.Refresh(true))

Actually, they are different:
$('#GridName').data('kendoGrid').dataSource.read() refreshes the uid attributes of the table row
$('#GridName').data('kendoGrid').refresh() leaves the same uid

What you have to do is just add an event
.Events(events => events.Sync("KendoGridRefresh"))
in your kendoGrid binding code.No need to write the refresh code in ajax result.
#(Html.Kendo().Grid<Models.DocumentDetail>().Name("document")
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Model(model => model.Id(m => m.Id))
.Events(events => events.Sync("KendoGridRefresh"))
)
.Columns(columns =>
{
columns.Bound(c => c.Id).Hidden();
columns.Bound(c => c.UserName).Title(#Resources.Resource.lblAddedBy);
}).Events(e => e.DataBound("onRowBound"))
.ToolBar(toolbar => toolbar.Create().Text(#Resources.Resource.lblNewDocument))
.Sortable()
.HtmlAttributes(new { style = "height:260px" })
)
And you can add the following Global function in any of your .js file. so, you can call it for all the kendo grids in your project to refresh the kendoGrid.
function KendoGridRefresh() {
var grid = $('#document').data('kendoGrid');
grid.dataSource.read();
}

In my case I had a custom url to go to each time; though the schema of the result would remain the same.
I used the following:
var searchResults = null;
$.ajax({
url: http://myhost/context/resource,
dataType: "json",
success: function (result, textStatus, jqXHR) {
//massage results and store in searchResults
searchResults = massageData(result);
}
}).done(function() {
//Kendo grid stuff
var dataSource = new kendo.data.DataSource({ data: searchResults });
var grid = $('#doc-list-grid').data('kendoGrid');
dataSource.read();
grid.setDataSource(dataSource);
});

I used Jquery .ajax to get data. In order to reload the data into current grid, I need to do the following:
.success (function (result){
$("#grid").data("kendoGrid").dataSource.data(result.data);
})

You can use the below lines
$('#GridName').data('kendoGrid').dataSource.read();
$('#GridName').data('kendoGrid').refresh();
For a auto refresh feature have a look here

By using following code it automatically called grid's read method and again fill grid
$('#GridName').data('kendoGrid').dataSource.read();

An alternative way to reload the grid is
$("#GridName").getKendoGrid().dataSource.read();

You can always use $('#GridName').data('kendoGrid').dataSource.read();. You don't really need to .refresh(); after that, .dataSource.read(); will do the trick.
Now if you want to refresh your grid in a more angular way, you can do:
<div kendo-grid="vm.grid" id="grid" options="vm.gridOptions"></div>
vm.grid.dataSource.read();`
OR
vm.gridOptions.dataSource.read();
And don't forget to declare your datasource as kendo.data.DataSource type

I want to go back to page 1 when I refresh the grid. Just calling the read() function will keep you on the current page, even if the new results don't have that many pages. Calling .page(1) on the datasource will refresh the datasource AND return to page 1 but fails on grids that aren't pageable. This function handles both:
function refreshGrid(selector) {
var grid = $(selector);
if (grid.length === 0)
return;
grid = grid.data('kendoGrid');
if (grid.getOptions().pageable) {
grid.dataSource.page(1);
}
else {
grid.dataSource.read();
}
}

In order to do a complete refresh, where the grid will be re-rendered alongwith new read request, you can do the following:
Grid.setOptions({
property: true/false
});
Where property can be any property e.g. sortable

You may try:
$('#GridName').data('kendoGrid').dataSource.read();
$('#GridName').data('kendoGrid').refresh();

Just write below code
$('.k-i-refresh').click();

$("#theidofthegrid").data("kendoGrid").dataSource.data([ ]);

If you are desiring the grid to be automatically refreshed on a timed basis, you can use the following example which has the interval set at 30 seconds:
<script type="text/javascript" language="javascript">
$(document).ready(function () {
setInterval(function () {
var grid = $("#GridName").data("kendoGrid");
grid.dataSource.read();
}, 30000);
});
</script>

You can also refresh your grid with sending new parameters to Read action and setting pages to what you like :
var ds = $("#gridName").data("kendoGrid").dataSource;
ds.options.page = 1;
var parameters = {
id: 1
name: 'test'
}
ds.read(parameters);
In this example read action of the grid is being called by 2 parameters value and after getting result the paging of the grid is in page 1.

The default/updated configuration/data of the widgets is set to automatically bind to an associated DataSource.
$('#GridId').data('kendoGrid').dataSource.read();
$('#GridId').data('kendoGrid').refresh();

The easiest way out to refresh is using the refresh() function.
Which goes like:
$('#gridName').data('kendoGrid').refresh();
while you can also refresh the data source using this command:
$('#gridName').data('kendoGrid').dataSource.read();
The latter actually reloads the data source of the grid. The use of both can be done according to your need and requirement.

I see that a lot of answers here suggest calling both dataSource.read and grid.refresh, however, internally the grid listens for dataSource changes and upon a change it will refresh itself. In other words executing both dataSource.read and grid.refresh will result in refreshing the grid twice, which is unnecessary. Calling just dataSource.read is enough.

common js function for refresh kendo grid
function refreshKendoGrid(id) {
var grid = $("#" + id).data("kendoGrid");
if (grid) {
grid.dataSource.read();
}
}

My solution is:
var gridObj = $('#GridName').data('kendoGrid');
gridObj.dataSource.read();
gridObj.refresh();
Works also for other object functions

$("#grd").data("kendoGrid").dataSource.read();

$('#GridName').data('kendoGrid').dataSource.read(); //first you have to read the datasource data
$('#GridName').data('kendoGrid').refresh(); // after that you can refresh

Related

How to mark Kendo Grid's cell as edited?

I'm dynamically editing some fields using JavaScript. But the problem is Kendo's dataSource doesn't recognize them as changed cells.
Grid's edit mode is InCell.
This is my current JavaScript code:
tablesGrid.tbody.find("input[type='checkbox']").each(function () {
$(this).on('change', function () {
var isChecked = $(this).prop('checked');
var dataItem = tablesGrid.dataItem($(this).closest('tr'));
var currentTr = $(this).closest('tr');
var i = $('td:visible', currentTr).index($(this).closest('td'));
var head = tablesGrid.thead.find('th:visible')[i];
var headName = $(head).prop('dataset').field;
tablesGrid.editCell($(this).closest('td'));
dataItem[headName] = isChecked;
tablesGrid.refresh();
});
});
And if you're wondering about this code, I should note that I'm using client template to show checkboxes. But I don't want the user to double click the cell for editing, once to put it in the edit mode, and another one to change the checkbox. I'm not sure if I'm using the right solution, but the JS code works for sure. If I click in the cell and put it in the edit mode, I'll see the change.
#(Html.Kendo().Grid<grid>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(x => x.field)
.ClientTemplate("<input type='checkbox' class='checkbox-inline' #=field? checked='checked':''# />")
.EditorTemplateName("Checkbox");
Well, the best solution I came up with is to put the cell in edit mode when mouse enters that cell! So instead of the entire JS code in the question, I simply use this.
tablesGrid.bind('dataBound', function () {
tablesGrid.tbody.find('td').each(function () {
$(this).mouseenter(function () {
tablesGrid.editCell(this);
});
});
});
Please let me know if you have any better or more efficient way to use editable
checkboxes inside a Grid.

Kendo grid's Select command operation configuration

Among Edit and Destroy, Kendo grid has a Select command too. But it seems there's no configuration for this operation. Do you know how can I use it? Any better way of JS binding like custom commands? Notice that it doesn't have a click event.
This line is in my Kendo grid, columns section.
columns.Command(command => { command.Select(); command.Edit(); command.Destroy(); });
Well, I found no better way than using a custom command.
Custom command inside grid:
command.Custom("select").Text("Select").Click("select");
and JS handler code:
<script>
function select(e) {
var grid = $("#grid").data("kendoGrid");
var item = grid.dataItem(grid.select());
var data = item.Title;
alert(data);
}
</script>
Another way to call this will be:
function select(e){
var row = $(e.currentTarget).closest("tr");
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
alert(dataItem.Title);
}

Kendo Grid: Keep custom popup open after save new record

I've got a custom popup editor template for my Kendo Grid which contains tabs. One of the tabs is to have a second Kendo Grid of records relating to the record being edited.
I'd like to be able to create a new record and immediately start adding the related records, without having to re-open the newly created record. Obviously, I have to first save the record in order for its ID to be generated.
I've managed to prevent the popup editor closing when new records are saved, but I think the popup window is no longer bound to the model at this point.
Is there a way I can rebind the window to the model so I can carry on editing and adding the related records?
Thanks
Edit: Here's the technique for keeping the editor open:
The grid's edit and save events:
edit: function(e){
var editWindow = this.editable.element.data("kendoWindow");
editWindow.bind("close", onWindowEditClose);
},
save: function(e){
if (e.model.isNew()) {
preventCloseOnSave = true;
} else {
preventCloseOnSave = false;
}
}
The onWindowEditClose:
var onWindowEditClose = function(e) {'
if (preventCloseOnSave) {
e.preventDefault();
preventCloseOnSave = false;
}
};
I ended up using a slightly clunky workaround, but other than a minor UI 'flash' it works okay.
The Grid has a rowTemplate, so I've added the record's ID field to the TR tags so I can find them by ID. I then have a function that runs on the complete event when a new record is created which finds the new row and immediately opens it:
var ds = new kendo.data.DataSource({
// ...
transport: {
create: {
url: '/url/to/create',
dataType: 'json',
type: 'post',
complete: recordCreated
}
});
function recordCreated(e) {
"use strict";
var id = e.responseJSON.data[0].id,
grid = $('#grid').data("kendoGrid"),
row = grid.tbody.find("tr[data-id='" + id + "']");
grid.editRow(row);
}
On a conceptual level, you could intercept the POST action that saves the record to the database and get the saved data on return. Note that your POST action must return the saved object (as is expected). You can hook into this event by using the requestEnd method of the Kendo UI Datasource object that supports your grid and bind the saved record to your edit window (as long as you have a reference to it).
var ds = new kendo.data.DataSource({
// ...
requestEnd: function (e) {
kendo.bind(editWindow, e.response); // bind the returned data to your edit window
}
});
The understanding of the kendo ui structure (which can be tedious at times) is important to getting anything done with it. The closing of the popup that allows inserting is done in the dataBinding event. Therefore, that is the place we need to prevent it from:
$("#yourgrid").kendoGrid({
dataSource: yourDataSource,
columns: [
{ field: "YouColumn", title: "YourTitle", ... },
...
]
.
.
.
editable: "popup",
dataBinding: function(e){
//this is the key to keeping the popup open
e.preventDefault();
},
save: function (e) {
//whatever you need to do here
}
.
.
.
});
Hope this helps someone.
//Houdini

How to change columns set of kendo grid dynamically

I am trying to change the columns collection of my Kendo grid in the below way.
var grid = $("#grid").data("kendoGrid");
$http.get('/api/GetGridColumns')
.success(function (data) {
grid.columns = data;
})
.error(function (data) {
console.log(data);
});
This is changing the column collection but not reflecting immediately in my grid. But when I try to perform some actions in the grid (like grouping), then my new column set is appearing.
Please let me know how can I achieve this.
Regards,
Dilip Kumar
You can do it by setting the KendoUI datasource, destroy the grid, and rebuild it
$("#load").click(function () {
var grid = $("#grid").data("kendoGrid");
var dataSource = grid.dataSource;
$.ajax({
url: "/Home/Load",
success: function (state) {
state = JSON.parse(state);
var options = grid.options;
options.columns = state.columns;
options.dataSource.page = state.page;
options.dataSource.pageSize = state.pageSize;
options.dataSource.sort = state.sort;
options.dataSource.filter = state.filter;
options.dataSource.group = state.group;
grid.destroy();
$("#grid")
.empty()
.kendoGrid(options);
}
});
});
here you can just do this :
var options = grid.options;
options.columns = state.columns;
where you can retrieve the columns in a session or in a db
This jsfiddle - Kendo UI grid dynamic columns can help you - using kendo.observable.
var columns = data;
var configuration = {
editable: true,
sortable: true,
scrollable: false,
columns: columns //set the columns here
};
var grid = $("#grid").kendoGrid(configuration).data("kendoGrid");
kendo.bind($('#example'), viewModel); //viewModel will be data as in jsfiddle
For the ones who are using Kendo and Angular together, here is a solution that worked for me:
The idea is to use the k-rebind directive. From the docs:
Widget Update upon Option Changes
You can update a widget from controller. Use the special k-rebind attribute to create a widget which automatically updates when some scope variable changes. This option will destroy the original widget and will recreate it using the changed options.
Apart from setting the array of columns in the GridOptions as we normally do, we have to hold a reference to it:
vm.gridOptions = { ... };
vm.gridColumns = [{...}, ... ,{...}];
vm.gridOptions.columns = vm.gridColumns;
and then pass that variable to the k-rebind directive:
<div kendo-grid="vm.grid" options="vm.gridOptions" k-rebind="vm.gridColumns">
</div>
And that's it when you are binding the grid to remote data (OData in my case). Now you can add or remove elements to/from the array of columns. The grid is going to query for the data again after it is recreated.
When binding the Grid to local data (local array of objects), we have to somehow postpone the binding of the data until the widget is recreated. What worked for me (maybe there is a cleaner solution to this) is to use the $timeout service:
vm.gridColumns.push({ ... });
vm.$timeout(function () {
vm.gridOptions.dataSource.data(vm.myArrayOfObjects);
}, 0);
This has been tested using AngularJS v1.5.0 and Kendo UI v2016.1.226.
I'm use this code for change columns dynamic:
kendo.data.binders.widget.columns = kendo.data.Binder.extend({
refresh: function () {
var value = this.bindings["columns"].get();
this.element.setOptions({ columns: value.toJSON });
this.element._columns(value.toJSON());
this.element._templates();
this.element.thead.empty();
this.element._thead();
this.element._renderContent(this.element.dataSource.view());
}
});
Weddin
Refresh your grid
.success(function (data) {
grid.columns = data;
grid.refresh();
})
Here is what i use
var columns = [];//add the columns here
var grid = $('#grid').data('kendoGrid');
grid.setOptions({ columns: columns });
grid._columns(columns);
grid._templates();
grid.thead.empty();
grid._thead();
grid._renderContent(grid.dataSource.view());
I think a solution for what you are asking is to call the equivalent remote DataSource.read() method inside of the function. This is what I used to change the number of columns dynamically for local js data.
$("#numOfValues").change(function () {
var columnsConfig = [];
columnsConfig.push({ field: "item", title: "Metric" });
// Dynamically assign number of value columns
for (var i = 1; i <= $(this).val(); i++) {
columnsConfig.push({ field: ("value" + i), title: ("201" + i) });
}
columnsConfig.push({ field: "target", title: "Target" });
columnsConfig.push({ command: "destroy", title: "" });
$("#grid").data("kendoGrid").setOptions({
columns: columnsConfig
});
columnDataSource.read(); // This is what reloads the data
});
Refresh the grid
$('#GridName').data('kendoGrid').dataSource.read();
$('#GridName').data('kendoGrid').refresh();
Instead of looping through all the elements. we can remove all the data in the grid by using a single statement
$("#Grid").data('kendoGrid').dataSource.data([]);
If your grid is simple and you don't need to configure special column-specific settings, then you can simply omit the columns argument, as suggested in the API reference.
Use autogenerated columns (i.e. do not set any column settings)
... and ....
If this [column] setting is not specified the grid will create a column for every field of the data item.
var newDataSource = new kendo.data.DataSource({data: dataSource}); $("#grid").data("kendoGrid").setDataSource(newDataSource);
$("#grid").data("kendoGrid").dataSource.read();
After fighting this for a day and seeing hints in this thread that Kendo had simplified this problem, I discovered you can just use setOptions with a single property.
.success(function (data) {
grid.setOptions({
columns: data,
});
})
Grid Set Options

How to bind events to element generated by ajax

I am using RenderPartial to generate CListView and all the contents generated properly and good pagination is working fine too. But when I added my custom JS to elements generated by the CListview it works fine for the the fist page content but when i use pagination and click to page 2 then the JS binding fails.
Is there any other way to bind custom event to elements generated in YII CListview I had tried using live, and on nothing work for me here is my js file.
I think I have to call my function on every ajax load in but how can I achieve in yii
This is the script I am using to update ratings on server with button click and this the element for which these forms and buttons are defined are generated by CListview in yii
$(document).ready(function(){
$('form[id^="rating_formup_"]').each(function() {
$(this).live('click', function() {
alert("hi");
var profileid= $(this).find('#profile_id').attr('value');
var userid= $(this).find('#user_id').attr('value');
console.log(userid);
var data = new Object();
data.profile_id=profileid;
data.user_id=userid;
data.liked="Liked";
$.post('profile_rating_ajax.php', data, handleAjaxResponse);
return false;
});
});
});
You can also try CGridView.afterAjaxUpdate:
'afterAjaxUpdate' => 'js:applyEventHandlers'
The $.each method will loop only on existing elements, so the live binder will never see the ajax-generated content.
Why don't you try it like this:
$(document).ready(function(){
$('form[id^="rating_formup_"]').live('click', function() {
alert("hi");
var profileid= $(this).find('#profile_id').attr('value');
var userid= $(this).find('#user_id').attr('value');
console.log(userid);
var data = new Object();
data.profile_id=profileid;
data.user_id=userid;
data.liked="Liked";
$.post('profile_rating_ajax.php', data, handleAjaxResponse);
return false;
});
});
This problem can be solved by two ways:
Use 'onclick' html definitions for every item that is going to receive that event, and when generating the element, pass the id of the $data to the js function. For example, inside the 'view' page:
echo CHtml::htmlButton('click me', array('onclick'=>'myFunction('.$data->id.')');
Bind event handlers to 'body' as the framework does. They'll survive after ajax updates:
$('body').on('click','#myUniqueId',funcion(){...});

Resources