How to change columns set of kendo grid dynamically - kendo-ui

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

Related

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

Three level jQGrid only for some rows

I have a two level jqGrid (grid/subgrid) implementation that works very fine.
Now I have a requirement that push me to implement a third level subgrid in only some of the second level rows.
Is there any way to exclude the opening of the third level if any condition on the row does not permit it?
Thanks very much
EDIT as per #Oleg answer
I have implemented the more complex logic example as in the referenced answer, that is
loadComplete: function() {
var grid = $("#list");
var subGridCells = $("td.sgcollapsed",grid[0]);
$.each(subGridCells,function(i,value){
[...]
var rowData = grid.getRowData( ??? );
});
}
Can I use any field to retrieve the rowData in the each loop?
If I understand your question correctly you can do the same like I described in the answer, but do this on the second level of subgrids. To hide "+" icon in some rows you need just execute .unbind("click").html(""); on "td.sgcollapsed" elements of the second level subgrids.
UPDATED: The demo demonstrate how you can get rowid and use getLocalRow (alternatively getRowData) to hide selective subgrid icons ("+" icons). I used the following loadComplete code in the demo:
loadComplete: function () {
var $grid = $(this);
$.each($grid.find(">tbody>tr.jqgrow>td.sgcollapsed"), function () {
var $tdSubgridButton = $(this),
rowid = $tdSubgridButton.closest("tr.jqgrow").attr("id"),
rowData = $grid.jqGrid("getLocalRow", rowid);
if (rowData.amount > 250 ) {
$tdSubgridButton.unbind("click").html("");
}
});
}

Reloading/refreshing Kendo Grid

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

Get all the checked rows in a kendo grid

I have a Kendo grid with a checkbox as a column along with other columns. I want to get all the rows where the checkbox is checked.
Please give me some idea.
Why not use the multi select feature of Kendo ui Grid
var checkDataSource = new kendo.data.DataSource({
data: checks
});
$("#CheckGrid").kendoGrid({
dataSource: checkDataSource,
change: CheckGridOnChange,
selectable:"multiple",
...
});
function CheckGridOnChange() {
var data = checkDataSource.view(),
selected = $.map(this.select(), function(item) {
return data[$(item).index()].CheckId;//CheckId is my unqiue id for my data, yours would probably be different
});
var ids = selected.join(",");
}
Ref url: Kendo ui grid Events Just hold control and select multiple rows

Resources