Kendo UI Grid - How to Bind to Child Properties - kendo-ui

How to bind a column/field to a child property of the json result in the model settings of the Kendo grid (in javascript)? For example, I want the grid to contain columns: FName, LName, Street and Address. Basically I want to flatten the hierarchical structure returned by the web service.
Kendo Settings
fields: {
FName: { type: "string" },
LName: { type: "string" },
// How to map to child properties below?
Street: { field: "Address.Street" }, // this is wrong
City: { field: "Address.City" } // this is wrong
}
JSON
{
"FName": "William",
"LName ": "Shakespeare",
"Address":
{
"Address": "123 Street Ln",
"City": "Philadelphia"
}
}

You don't do it like that. You need to create a class 'Model' that flattens the data graph. You will be able to use lazy loading during the construction of the Model. Either send this Model to the View via the controller or attach it to a larger ViewModel (just a Model of Models not MVVM) that is sent to the View. Then bind this to the Grid.
But, you will be happier to use Ajax loading of the same Model as JSON, which is what I think you are trying to do.
Model
public class ContactModel
{
public string FName { get; set; }
public string LName { get; set; }
public string Address { get; set; }
public string City { get; set; }
public ContactModel()
{}
public ContactModel(Contact contact) // IContact is better if you have Interfaces
{
FName = contact.FName;
LName = contact.LName;
Address = contact.Address.Address;
City = contact.Address.City;
}
// Neat Linq trick to convert database query results directly to Model
public static IList<ContactModel> FlattenToThis(IList<Contact> contacts)
{
return contacts.Select(contact => new ContactModel(contact)).ToList();
}
}
Controller
public JsonResult ReadContacts([DataSourceRequest]DataSourceRequest request)
{
var contacts = _contactsDataProvider.Read(); // Your database call, etc.
DataSourceResult result = ContactModel.FlattenToThis(contacts).ToDataSourceResult(request);
return Json(result, JsonRequestBehavior.AllowGet);
}
But I don't think Will ever made it to Philly. ;)

Related

How to query and return all documents in documentdb using linq

let problemDocument = documentClient.CreateDocumentQuery<ProblemDatabaseModel>("")
problemDocument
doesn't seem to work
(problemDocument.Select(fun problem -> problem))
doesn't seem to work
(problemDocument.Where(fun problem -> problem.id = problem.id))
doesn't seem to work either. Any ideas?
If you want to query all document in document db, please try to below code:
documentClient.CreateDocumentQuery<ProblemDatabaseModel>("").ToList();
Please note that, we can store different json entity in documentDB, if document property does not in your data model, it will give a default value. I have a simple test for this:
Data model:
public class Cred
{
[JsonProperty(PropertyName = "id")]
public string ID { get; set; }
[JsonProperty(PropertyName = "title")]
public string Title { get; set; }
[JsonProperty(PropertyName = "credits")]
public int Credits { get; set; }
[JsonProperty(PropertyName = "authordetails")]
public AuthDetail AuthInfo { get; set; }
}
If json data in documentDB is:
{
"id": "CDC103",
"title": "Fundamentals of database design",
"authordetails": {
"Name": "dave",
"Age": 33
},
"custom":"test"
}
client.CreateDocumentQuery<Cred>(UriFactory.CreateDocumentCollectionUri("jambordb", "jamborcols")).ToList();
Here is the result:
From the screenshot we know that, the property "custom" will not included in our data model. and the credits will give a default value 0.

Kendo Grid Server Side Filtering with MVC

I have a grid with Web Api server side sorting, which works. I have a requirement to add filtering. When the grid's datasource sends the filtering arguments to the Web Api controller, the Filter object is always 'empty', not null. Here is my setup
Grid datasource:
var myTeamGridDataSource = new kendo.data.DataSource({
serverPaging: true,
serverSorting: true,
serverFiltering: true,
schema: {
data: "data",
total: "count"
},
pageSize: 10,
transport: {
read: {
url: baseMyTeamUrl, // web api
dataType: "json",
type: "POST",
}
},
sort: {
field: "Name",
dir: "asc"
}
});
The Action:
public HttpResponseMessage KendoGridMyTeam(GridInputModel inputModel)
{
...
}
GridInputModel.cs
public class GridInputModel
{
public int Page { get; set; }
public int PageSize { get; set; }
public int Skip { get; set; }
public int Take { get; set; }
public List<GridInputSortModel> Sort { get; set; }
public List<GridInputFilterModel> Filter { get; set; }
}
GridInputFilterModel.cs
public class GridInputFilterModel
{
public GridInputFilterModel()
{
filters = new List<GridInputFilterModel>();
}
public string field { get; set; }
public string Operator { get; set; }
public object value { get; set; }
public string logic { get; set; }
public List<GridInputFilterModel> filters { get; set; }
}
The Request Body
take=10&skip=0&page=1&pageSize=10&sort[0][field]=Name&sort[0][dir]=asc
&filter[filters][0][field]=Name
&filter[filters][0][operator]=eq
&filter[filters][0][value]=cling
&filter[logic]=and
The GridInputModel "GridInputModel inputModel" is instantiated, and the sort object is preset and that feature works just fine. But the filter, when set in the client and sent to the server is empty. After a bunch of searching, I cannot find a modern example of server side grid filtering. You may suggest that I use the Kendo.Mvc library with:
[DataSourceRequest] DataSourceRequest request
This ALSO creates a Filter object in the Request but the filters are also empty. Any suggestions? One option, that I would hesitate to use, is to use parameterMap and send the filter along on the querystring. If I have to, fine, but somebody has to have this working.
Whats happening is that your application serverside isn't deserializing the filter objects properly. You can view this if you set the parameter to an object and view the actual JSON that is sent. Your filter will be present in the string. Use Parameter map and format the filter array before its sent and you might one to overload the DataSourceClass that kendo uses. I had the same issue and had to create my own class and format the filters before sending. The issue that messing up your filters is the operator property in the filter array.
In your javascript try this:
var grid = $("#YourGridId").data("kendoGrid");
var $filter = new Array();
$filter.push({ field: "Name", operator: "eq", value: "cling" });
grid.dataSource.filter($filter);
and in your controller method you need this signature:
public ActionResult ReadData([DataSourceRequest]DataSourceRequest request){
...
}
I am using MVC instead of WebApi, but I was getting the same symptom of a null filter passed to my controller method. I, too, went down the rabbit hole of creating my own model to handle the request parameter sent to my controller method, trying to parse Kendo's filter structure, etc. I finally got it to work by following this example on Falafel's blog. Specifically, you need to make the changes listed below to your code.
In the end, the technique shown below makes it very easy to implement server processing for Kendo's DataSource (once you know all the required pieces to make it work).
Grid DataSource: You have to match all the (case-sensitive) fields coming back from the server. I left out errors, and it stopped working. You may have to change the type to get it working with WebApi.
type: "aspnetmvc-ajax",
schema: {
data: "Data",
total: "Total",
errors: "Errors",
model: {
id: "YourKeyFieldName"
}
},
The Action: Yes, you need to use Kendo's DataSourceRequest object with its attribute .
using Kendo.MVC.UI;
using Kendo.MVC.Extensions;
[HttpPost]
public ActionResult KendoGridMyTeam([DataSourceRequest] DataSourceRequest request)
{
...
return Json(yourDataVariable.ToDataSource(request));
}

Kendo UI Treeview data bind to XML: how does it bind to "id"?

I have difficulties understanding the inner workings of the TreeView widget. I am referring to the Kendo code library example, specifically the Ajax loading snippet:
//Ajax binding data
public JsonResult Employees(string id)
{
XElement element = XElement.Load((Server.MapPath("~/App_Data/employees.xml")));
IEnumerable<Employee> result;
if (!string.IsNullOrEmpty(id))
{
//search for id and return it's children
result = FindByID(id, element.Element("Employee")).Element("items").Elements("Employee").Select(e => ToEmployee(e));
}
else
{
//return first level nodes
result = element.Elements("Employee").Select(e => ToEmployee(e)) ;
}
return Json(result, JsonRequestBehavior.AllowGet);
}
//Find the XML element by Id
private XElement FindByID(string id, XElement element)
{...}
//Convert XML element to Object
private Employee ToEmployee(XElement element)
{
return new Employee()
{
id = int.Parse(element.Element("employeeId").Value),
name = element.Element("name").Value,
hasChildren = element.Element("items") != null
};
}
This is the Model used, which corresponds to the actual XML structure:
public class Employee
{
public int id { get; set; }
public string name { get; set; }
public bool hasChildren { get; set; }
public List<Employee> items { get; set; }
}
The View executes the following code:
#(Html.Kendo().TreeView()
.Name("ajaxTree")
.DataTextField("name")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("Employees", "Home");
});
})
)
What bothers me is the fact that the Model needs to be implemented exactly as in this example. Specifically, the "id" and "hasChildren" properties need to be specified exactly in this manner. Modifying, for example, "id" into "Id" would render this example ineffective and the TreeView would not load. Can somebody help me with the following?
How is the binding actually accomplished?
Why must I design my model with lower-case properties? (I know it sound weird, but it conflicts with the rest of my (group) project's formatting...)
Is there a way to bind the Kendo required "id" and "hasChildren" to other properties (same function, different name)?
Not sure if you got an answer for your question.
This link http://demos.kendoui.com/web/treeview/remote-data.html will help you understand how your model data is bound to treeview. Please go through below links.
HierarchicalDataSource - http://docs.kendoui.com/api/framework/hierarchicaldatasource
DataSource - http://docs.kendoui.com/api/framework/datasource
Model - http://docs.kendoui.com/api/framework/model
For question #2, #3
Yes, it is possible to configure your model properties as below:
schema: {
model: {
id: "EmployeeId",
hasChildren: "HasEmployees",
children: "EmployeeArray"
}
}

Passing data from View to Controller action

I have a View that gets some bits of data via Action methods that return JSON data.
Depending on the combination of selected options, the user can fill some fields in a page.
What is the best way to pass the data back to a controller, in order to be saved?
The fields that contain data vary on the options selected;
I don't have a ViewModel object with all fields bound to the View.
At the moment I have this:
#Ajax.BeginForm("MyAction", null, new AjaxOptions
{
}, new { #id = "SaveForm" } )
{
.....
#Html.RadioButton("SomeRadioButton", "bla", false, new { #id = "SomeRadioButton" })
.....
#Html.TextArea("SomeTextArea", new { #id = "SomeTextArea" })
.....
Save
}
How do I get all of those control values in the Action?
I can add something like:
public void MyAction(FormCollection form)
{
.........
}
But I don't really like this option.
What's the cleanest way to implement this?
Thanks in advance
You could define a view model:
public class MyViewModel
{
public string SomeRadioButton { get; set; }
public string SomeTextArea { get; set; }
...
}
and then have your controller action take this view model as argument and leave the default model binder do its job:
[HttpPost]
public void MyAction(MyViewModel model)
{
...
}
I would also take advantage of this view model in the view in order to use strongly typed versions of the helpers:
#Ajax.BeginForm("MyAction", null, new AjaxOptions { }, new { #id = "SaveForm" })
{
#Html.RadioButtonFor(x => x.SomeRadioButton)
...
#Html.TextAreaFor(x => x.SomeTextArea)
...
<button type="submit">Save</button>
}
You can (and mostly should) use custom class for this, which will hold all fields. Read further about Model Binding - that's the way to do it with MVC.

Complex type in WebGrid

I have, surprisingly, been searching on the internet how to bind a webgrid column from a complex type that is data source last 3 hours. But I could not find any useful information.
there is a topic on Complex WebGrid Binding in MVC 3, but it did not work in my scenario.
To simplify it, let's say I have a list of Employee objects that I populate WebGrid from, each Employee have Address property which is Address type.
I would like to show the City property of Address field in the WebGrid along with other fields of Employee.
I assumed that grid.Column("Address.City") would work, but it does not. Is that something not supported, or I am doing something wrong.
Thanks for your help.
Regards
AnarchistGeek
I could not see how your answer was fixing the issue until I realised that what I was missing is that sometimes the property can be null but instead of a null reference error you get the error Column "Address.City" does not exist. unless you check for null in the format property....I found the the answer here
#functions{
public class Employee
{
public string Name { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string City { get; set; }
}
}
#{
var myClasses = new List<Employee>{
new Employee { Name="A" , Address = new Address{ City="AA" }},
new Employee { Name="B" , Address = new Address{ City="BB" }},
new Employee { Name="C" , Address = new Address{ City=null }},
new Employee { Name="D" , Address = null},
};
var grid = new WebGrid(source: myClasses);
}
#grid.GetHtml(
columns: grid.Columns(grid.Column("Address.City",
header: "City",
format: #<text>#if (item.Address != null)
{#item.Address.City}
</text>),
grid.Column("Name")))
This is the answer I got in ASP.NET forums and I wanted post it here in case others may need that.
The thread link is http://forums.asp.net/p/1718114/4586676.aspx/1?Re%20Complex%20data%20type%20in%20WebGrid
and the solution is(Tested):
#functions{
public class Employee
{
public string Name { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string City { get; set; }
}
}
#{
var myClasses = new List<Employee>{
new Employee { Name="A" , Address = new Address{ City="AA" }},
new Employee { Name="B" , Address = new Address{ City="BB" }},
new Employee { Name="C" , Address = new Address{ City="CC" }},
new Employee { Name="D" , Address = new Address{ City="DD" }},
};
var grid = new WebGrid(source: myClasses);
}
#grid.GetHtml(
columns: grid.Columns(grid.Column("Address.City",header:"City"), grid.Column("Name")))
I hope it helps others.
Cheers.

Resources