Kendo UI Grid, sorting datasource groups - asp.net-mvc

I have a page that has a Kendo grid on it.
It is calling an ajaz web request to get its data.
Once the data has been returned it is grouped in the frontend.
The problem I am having is sorting the groups. What is the best way to do this?
My MVC view code looks something like this...
.DataSource(dataSource => dataSource
.Ajax()
.Group(groups =>
{
groups.Add(c => c.groupingField);
})
.Read(...))
I have tried to use the sort method but am not sure where to put it when the data is coming from an ajax call.

I found that adding the below line to the datasource call solved my problem...
.Sort(sort => sort.Add("FIELD_NAME").Ascending())

You need to provide groups in correct order in .Group() method. I don't have mvc version installed but for example it should be ok:
var groupList = new List<string> { "Gr1", "Gr2" };
.DataSource(dataSource => dataSource
.Ajax()
.Group(groups =>
{
groupList.Select(x => groups.Add(x));
})
.Read(...))

Related

Make Kendo ASP.NET MVC inCell Editable based on Viewbag condition

Is it possible to make a Kendo MVC grid .Editable() based on a function that allows editing ONLY if you have a certain Viewbag?
I have a viewbag that is Viewbag.DisplayButton. That viewbag is only 'true' if you have a dev role (so non-devs cannot edit anything). How can I make this work with .Editable() so that you can only edit cells if you have that viewbag?
Currently if I set Editable(true) then anyone (devs, customers, literally anyone) can edit the cell. If I set it to Editable(false) then no one, including devs, can edit it. So I need a function that does it only if you have that specific viewbag.
Use a Razor code block for this. You can assign the Grid definition to a variable, then execute the conditional logic and add the additional configurations, if any. Finally call the Render method. Here is an example:
<h3>Some content</h3>
#{
var isAdmin = true;
var grid = (Html.Kendo().Grid<MyModel>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(p => p.MyModelID).Filterable(false);
columns.Bound(p => p.SomeModelProperty);
})
.Pageable()
.Scrollable()
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Model(m=>m.Id("MyModelID"))
.Read(read => read.Action("Read", "Grid"))
)
);
if (User.IsInRole("Admin"))
{
grid.Editable(e=>e.Mode(GridEditMode.InCell));
}
grid.Render();
}
<h3>Some other content</h3>

Kendo MVC Grid Default Sort by Multiple Column Fails

#(Html.Kendo().Grid<...>()
.Columns(columns =>
{
columns.Bound(j => j.Type);
columns.Bound(j => j.Code);
})
.Sortable(s => s.Enabled(true))
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Sort(p => { p.Add("Code").Ascending(); p.Add("Type").Ascending(); })
.Model(model => model.Id(j => j.ID))
.Read(...)
.ServerOperation(true)
)
)
I have a Kendo MVC Grid as above and want to sort it first by type, then by code.
I have found such implementation on official Telerik forum: Default Grid Sorting
However it seems it fails to work...
The records are sorted by two columns, and apparently it is sorted by Type, but it fails to sort by Code afterwards...As Default should after CG...
What am I missing and how can I fix the problem?
For anyone else looking for a solution, using the model property names worked for me, i.e.
.Sort(s =>
{
s.Add("Code").Ascending();
s.Add("Type").Ascending();
})
Try this way
.Sort(p=> {p.Add(s=>s.Code).Ascending(); p.Add(s=>s.Type).Ascending();})

Accessing row data from Kendo Grid ClientTemplate

I am trying to embed a chart in a Kendo Grid Cell, following this example: http://docs.telerik.com/kendo-ui/aspnet-mvc/helpers/grid/faq#how-do-i-use-a-kendo-ui-widget-inside-a-grid-client-column-template
I have managed to embed the graph in the grid, but I am unable to find a way to bind to row data.
The ViewModel has properties for each bar value - but how do I bind to those properties (maybe some #= ... # expression?).
I expect something similar to this:
#(Html.Kendo().Grid<ViewModel>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(p => p.DataID).Filterable(false);
columns.Template(#<text></text>).ClientTemplate(
Html.Kendo().Chart()
.Name("chart#=DataID#")
.Series(series =>
{
series.Bar("\\#= FirstBarValue \\#");
series.Bar("\\#= SecondBarValue \\#");
})
.ToClientTemplate().ToHtmlString()
);
})
.DataSource(dataSource => dataSource.Ajax().PageSize(20).Read(read => read.Action("Read", "Grid"))))
But the FirstBarValue and SecondBarValue are not properly evaluated, although DataID is. Maybe a different scope? I can only make it work with hard coded values.
Any suggestions?

How to update and reload the datasource of a Kendo UI MVC grid from clientside upon search

I have a kendo UI grid which is similar to this
#(Html.Kendo().Grid<MyViewModel>()
.Name("MyGrid")
.Columns(columns =>
{
columns.Bound(a => a.column1);
columns.Bound(a => a.column2;
}
.Pageable(page => page.PageSizes(true))
.Scrollable(src => src.Height("auto"))
.Sortable()
.Filterable()
.Reorderable(reorder => reorder.Columns(true))
.ColumnMenu()
.Events(e =>
{
e.DataBound("onDataBound");
})
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(10)
.Read(read => read.Action("GetMyList_Read", "MyController"))
)
)
The datasource on this grid is loaded from "GetMyList_Read" action upon page load. I have a filter which works by pushing filter parameters into the kendo builtin filters. And it works fine. I want to do search on the serverside code to improve performance, instead of loading the whole data to the client side and filter. Also one of the search parameters require searching a new DB table evertime search is performed so having a server side filer will help a lot.
You can just alter your read action to include
.Read(read => read.Action("GetMyList_Read", "MyController").Data("AddFilters"))
Then add some JavaScript to populate you filters something like this:
<script>
Function AddFilters()
{
Return { filter: "some value");
}
</script>
Then just alter your read action to accept the additional parameter.
Eg public jsonresult GetMyList_Read([DataSourceRequest] DataSourceRequest request, string filter)
Hopefully this gives you enough to work with but if you need a more complete example let me know and I will post something a bit more complete

Kendo mvc grid batch mode dataItem.set clears the dirty flags

When I change an amount, tick the checkbox etc, it triggers some javascript, which includes some code to set another field on the dataItem, so dataItem.Set ("Amount", 0);
I can set it using dataItem.Amount = 0; , but then I also need to update the contents of the cell. When I do set I obviously don't want the dirty flag clearing from other cells, as I haven't clicked 'Save changes' yet, so they are still 'dirty'.
I can't find any documentation on the .set method.
Any advice would be appreciated.
#(Html.Kendo().Grid<OurViewModel>()
.Name("Grid")
.DataSource(dataSource => dataSource
.Ajax()
.Model(model =>
{
model.Id(a => a.ID);
model.Field(a => a.Reference).Editable(false);
model.Field(a => a.Narrative).Editable(false);
model.Field(a => a.Include).Editable(true);
model.Field(a => a.Amount).Editable(true);
})
.Batch(true)
.Read(read => read.Action("_Read", "Home"))
.Update(update => update.Action("_Update", "Home"))
.ServerOperation(false)
.Events(events =>
{
events.Change("onDataSourceChange");
})
)
.Columns(columns =>
{
columns.Bound(a => a.Reference).Title("Reference");
columns.Bound(a => a.Narrative).Title("Narrative");
columns.Template(#<text></text>).Title("Include?")
.ClientTemplate("<input type='checkbox' #= Include ? checked='checked': '' # onclick='updateAmount(this, \"#= ID#\")' />");
columns.Bound(a => a.Amount).Title("Amount");
})
.Events(events =>
{
events.Save("onSave");
events.SaveChanges("onSaveChanges");
})
.ToolBar(toolbar =>
{
toolbar.Save();
})
.Editable(editable => editable.Mode(GridEditMode.InCell))
)
and the JS.
function updateAmount(cb, ourID) {
var checked = $(cb).is(':checked');
var grid = $('#Grid').data().kendoGrid;
var dataItem = grid.dataSource.get(ourID);
dataItem.set("Include", checked);
if (checked) {
dataItem.set("Amount", dataItem.get("OriginalAmount"));
} else {
dataItem.set("Amount", 0);
}
}
When calling the set method on an observable object (Note: Each dataItem in the dataSource in converted to a kendo ObservableObject when loaded) any widgets that our bound to the dataItem will be updated, in this case your grid is the bound widget.
If you set the value directly (i.e. dataItem.Amount = 0) none of the observable object's binding events will trigger and the grid (or any other widgets bound to the dataItem) will NOT update. You should always use set when modifying fields of an observable object in order to keep the UI up to date.
Within the dataSource, there are no dirty flags for the individual fields in the dataItem. The dataItem itself will have a field named "dirty" which will be set to true whenever ANY of its fields change. Changing more than 1 field will just keep setting dirty = true for the entire dataItem. You don't need to worry about tracking modified fields. Once a row is dirty it will stay dirty until you save the data.
When you save the contents of the grid (a.k.a. sync the dataSource) any (and only) rows with dirty = true will be sent to the server. Once saved, the dirty flags will be removed. On that note, you will want to refrain from using "dirty" as a table property in your database.
The kendo documentation at is pretty complete but I would highly recommend tracing through the kendo javascript code to really learn it. One last note, I started with the Kendo MVC approach hoping to leverage by C# knowledge but soon found it much easier to just code all the client side in JavaScript. All your C# code gets converted to rather verbose JavaScript anyway each time the server it hit. This puts unnecessary load on the server and makes client side debugging harder IMO.

Resources