Kendo grid's Select command operation configuration - kendo-ui

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);
}

Related

How to determine which row or control is making a DropDownList Read Data call

I have a DropDownListFor control inside a Kendo grid, and I need the value of another element in that row in order to pass a parameter to the DropDownList's server-side read method. It's a similar setup to the example here.
Here is the code which defines the DropDownListFor:
#(Html.Kendo().DropDownListFor(m => m)
.Name("LinkIdentifier")
.OptionLabel("---Select Form, etc.---")
.DataValueField("ID")
.DataTextField("Name")
.AutoBind(false)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("LinkTypeIdentifierDdl", "Alerts").Type(HttpVerbs.Post).Data("getCurrentLinkType");
}).ServerFiltering(true);
})
)
And here is the javascript function which is called in .Data:
function getCurrentLinkType() {
var grid = $("#linkGrid").data("kendoGrid");
var data = grid.dataSource.data();
var dataItem = data[0];
var valueForParameter = dataItem.SomeValue
//--snipped for brevity
}
The problem above is data[0]. It only points to the first row in the grid, which won't be correct if editing any other row. If I use a javascript debugger within this method and look at "this", it's the AJAX call which is referenced, not the dropdown control. I can't specify ".Data("getCurrentLinkType(this)")" as the method.
So, how can I determine which row/control has made the call to getCurrentLinkType?
There is no context passed from the Grid to the DropDownList to the Data function, so you need to figure it out yourself.
I have found 2 ways.
1:
// If your grid is single Selectable(), use the current selection
var dataItem = grid.dataItem(grid.select());
2:
// If your grid is not Selectable or is multi Selectable, get the row/tr closest to the editor and then get the dataItem from that
var dataItem = grid.dataItem($("#LinkIdentifier").closest("tr"));

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.

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

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

Add custom click event in each option of mvc3 dropdown in c#

I want to create custom dropdown in mvc3 c#, so there can be provision to add click event in each option of dropdown.But I don't want any alternative like jquery or create for loop to add attribute manually.Is there is any way to create custom dropdown using htmlhelper or base class.Please help me regarding this.
Suppose this is your dropdown then you use the following way to define events.
<%=Html.DropDownList("ddl", ViewData["MyList"] as SelectList, new { onchange = "this.form.submit()" })%>
And in your jquery code:
$(document).ready(function() {
$("#ddl").change(function() {
var strSelected = "";
$("#ddl option:selected").each(function() {
strSelected += $(this)[0].value;
});
var url = "/Home/MyAction/" + strSelected;
$.post(url, function(data) {
// do something if necessary
});
});
});

Resources