Kendo UI DropDown List does not accept JSON data? - kendo-ui

Using Kendo DropdownList for MVC, trying to identify why the DropdownList will not accept this data.
#(Html.Kendo().DropDownList()
.Name("CompanyList") //The name of the DropDownList is mandatory. It specifies the "id" attribute of the widget.
.DataTextField("Table")
.DataValueField("COM_NAME")
.DataSource(source =>
{
source.Custom() // Read(read =>
.Type("json")
.Transport(transport =>
{
transport.Read("GetallCompanies", "Home");
})
.ServerFiltering(true); //If true, the DataSource will not filter the data on the client.
})
.SelectedIndex(0) //Select the first item.
)
The raw data from the SQL action has this format:
"{\"Table\":[{\"ORG_ID\":265498,\"COMPORGID\":239597,\"COM_NAME\":\"ABC Rentals \"},{\"ORG_ID\":164929,\"COMPORGID\":239698,\"COM_NAME\":\"Asbury Machine Shop \"}]}"
Have referenced the Kendo docs and other SO examples. Put the JSON into a validator tool, says its correctly formatted.
In the page, the drop down has a left curly brace, { as the top item, and when clicking there are dozens of: Undefined.
The DataTextField was called "Table" because of the "Table" in the JSON array, but it was set to COM_NAME. The Controller Method,
[HttpGet]
public JsonResult GetallCompanies()
{
var ddx = CompInfo.GetAllCompanies(); //returns dataset
string thedata = JsonConvert.SerializeObject(ddx);
return Json(thedata, JsonRequestBehavior.AllowGet);
}

I don't think you need to use SerializeObject on ddx aswell as the Json method before returning to the client. Can you try changing GetAllCompanies to:
[HttpGet]
public JsonResult GetallCompanies()
{
var ddx = CompInfo.GetAllCompanies(); //returns dataset
//string thedata = JsonConvert.SerializeObject(ddx);
return Json(ddx);
}
Summary of the Json method:
Creates a Microsoft.AspNetCore.Mvc.JsonResult object that serializes the specified data object to JSON.

Try this:
Server-side: Leave the JsonConvert.SerializeObject line commented out.
Client-side: Add the following to the DropDownList configuration (e.g. after .SelectedIndex(0)):
.Schema(schema => schema.Data("Table"))

Related

KendoUI for ASPMVC TreeView: display the Json response on behalf of the Tree

I am trying to display a tree of categories with remote data binding.
here is the Controller method:
public JsonResult KendoTree(Guid? id)
{
var categoriesBO = _categoryManager.GetAllCategory().
Where(c=> id==null ? c.ParentId==null : c.ParentId == id).
Select(c=> new
{
id = c.Id,
Name = c.Name,
hasChildren = c.CategoryChilds.Any()
});
return Json(categoriesBO, JsonRequestBehavior.AllowGet);
}
here is the cshtml file
#{
ViewBag.Title = "KendoTree";
}
<h2>KendoTree</h2>
#Html.Kendo().TreeView().Name("Categories").DataSource(dataSource => dataSource
.Read(read => read.Action("KendoTree", "CategoryManagement")
)).DataTextField("Name")
The browser display the Json result(an array) on behalf of the tree.
Am I missing something?
I got it: I have to have a Controller action that returns a view then call the kendo Html helper from inside the related view.

Add custom data-* attributes to Kendo UI AutoComplete or ComboBox

Currently using the Kendo UI AutoCompleteFor() and ComboBoxFor() helper.
Noticing that they generate/render a bunch of <li>s.
How does one add additional custom data-* attributes to those <li>s?
Here's the current scenario:
The user starts typing stuff in the AutoCompleteFor
An ajax call is triggered to fetch some data related to what the
user has typed.
The obtained results are transformed into an
IEnumerable<SelectListItem>.
The result is then sent to Json. Json(result, JsonRequestBehavior.AllowGet)
My goal is to add one or more additional data-* attribute to each of these <li> generate lines so that I can fetch these data-* in the onChange() event.
How does one achieve this?
In addition, I'm aware that I could create my own .Template() and possibly achieve my task but I was curious if anyone knows of a different way to do this then having to create my own template.
Sincerely
Ok I've found a solution; I'll share it here in case anyone is interested.
Instead of transforming my obtained results into an IEnumerable<SelectListItem>, I simply transform this into an IEnumerable<CustomDTO>.
The CustomDTO class looks like this:
public class CustomDTO
{
public int Value { get; set; }
public string Text { get; set; }
public int Age { get; set; }
//Add whatever more properties you think you’ll need.
}
In my controller, I then do the following:
var result = _myService.GetData().ToList();
return Json(result, JsonRequestBehavior.AllowGet);
Where GetData() returns an IEnumerable<CustomDTO>.
Inside my View, I have an AutoCompleteFor() control to which I bind a client side
.Events(x => x.Select("onSelect") event handler.
The handler is defined like so:
function onSelect(e)
{
if (e.item == null) return;
var dataItem = this.dataItem(e.item.index());
var valueAttribute = dataItem.Value;
var textAttribute = dataItem.Text;
var ageAttribute = dataItem.Age; //This is how I get my additional value
//...code...
}
So that's it.

Restrict Kendo Grid to Current Route Id

I'm trying to include a Kendo UI ASP.NET MVC Grid on the Edit page of my MVC application and I would like to restrict that grid to only return values from the current route id. I've been researching ways to do this, but can't find anything that's exactly what I need, or I'm just too new at this to connect the dots.
My ideas so far are to either apply a filter to the DataSource or send a parameter to the controller and have it restrict the DataSourceResult.
For the DataSource filter in the view, I can do this:
.Filter(filters => { filters.Add(d => d.CompanyId).IsEqualTo(2); })
But I can't figure out how to replace the hardcoded 2 with the value from, say, #ViewContext.RouteData.Values["id"], or something.
Passing a parameter to the controller, I can get the following:
public ActionResult Divisions_Read([DataSourceRequest]DataSourceRequest request, int id)
{
using (var db = new AppContext())
{
IQueryable<Division> divisions = db.Divisions;
DataSourceResult result = divisions.ToDataSourceResult(request, division => new DivisionViewModel
{
DivisionId = division.DivisionId,
CompanyId = division.CompanyId,
CountryId = division.CountryId,
DivisionName = division.DivisionName
});
return Json(result);
}
}
But I have no idea how to use that id to basically add a "where CompanyId = Id" statement to the result.
Any ideas on what the best way to do this would be? Am I missing something really obvious?
Thanks!
ETA: Passing the parameter to the Controller through the Read action, as suggested by mmillican and other places in my research, and changing
DataSourceResult result = divisions.ToDataSourceResult(request, division => new DivisionViewModel
to
DataSourceResult result = divisions.Where(c => c.CompanyId == companyId).ToDataSourceResult(request, division => new DivisionViewModel
did the trick. That extra bit in the controller was what I was looking for, but couldn't seem to find anywhere.
Assuming you have a model for your page that looks like this:
public class MyViewModel
{
public int Id { get; set; } // assuming Id is what you want to filter by
// .. other VM properties
}
you can do something like this in your grid data binding
.DataSource(ds => ds
.Ajax()
.Model(mdl => mdl.Id(x => x.Id))
.Read("Divisions_Read", "Divisions", new { id = Model.Id })
)
in your controller, you would set the model's Id property to whatever ID that is in the route.

Getting filters used in KendoUI Grid

In KendoUI, I have a grid with filters on. I am more interested in knowing all the filters used by user for saving purpose so that next time user comes in, they can be auto-fill. How do I get all the filters used?
Not sure how your code looks but you should be able to get the Grid's datasource object and call the method filter() to get the currently applied datasource filters. Take a look at the example below taken from here:
<script>
var dataSource = new kendo.data.DataSource({
data: [
{ name: "Jane Doe" },
{ name: "John Doe" }
],
filter: { field: "name", operator: "startswith", value: "Jane" }
});
var filter = dataSource.filter();
console.log(filter.logic); // displays "and"
console.log(filter.filters[0]); // displays '{field: "name", operator: "startswith", value: "Jane"}'
</script>
Just to add to the answers above - if you want to do it purely on the front end without even targeting the actual data source - your can use the following...
var myGrid = $("#gridname").data("kendoGrid");
myGrid.dataSource.filter().filters[0];
You can than break this up into different parameters ...
myGrid.dataSource.filter().filters[0].field
myGrid.dataSource.filter().filters[0].operator
myGrid.dataSource.filter().filters[0].value
Hope this helps - cheers
My configuration is MVC with the data being fetched server-side. What I mean is that the grid calls this method to get its data:
public ActionResult Documents_Read([DataSourceRequest] DataSourceRequest request,
int documentType = (int)ApiGlobals.TrxTypes.חשבונית)
What I do is simple:
I capture the request object in a Session variable and then use the session variable whenever I need it. In the following example I use the filter to print only the documents filtered in the grid:
public ActionResult Documents_Read([DataSourceRequest] DataSourceRequest request,
int documentType = (int)ApiGlobals.TrxTypes.חשבונית)
{
Session["DocumentListFilter"] = request;
...
}
public ActionResult PrintListKendo(int documentType)
{
DataSourceRequest request = (DataSourceRequest)Session["DocumentListFilter"];
if (request == null)
{
request = new DataSourceRequest();
}
request.Page = 1;
request.PageSize = int.MaxValue;
IQueryable<Document> data = _db.GetDocuments()
.Where(d => d.TrxTypeId == (int)documentType);
DataSourceResult filteredData = data.ToDataSourceResult<Document, DocumentListSingleDocumentViewModel>(request,
d => ViewModelFactory.Create(d));
//... call the reporting package with the data, etc.
}
You can save the request object (=serialize it, or save it properties) to the database and reload it when the user opens the relevant page and the grid fetched its data,

How to pass in a SelectList and use associative select to get name from id?

Given the following code how can I select a list item in my view to get the name via an id? I just want to get the name value from the list via a local #id variable that maps to the lists id range.
This really has nothing to do with dropdowns...perhaps selectlist is the wrong container for associative look up dictionaries?
-- Controller
ViewBag.TypeId = new SelectList(db.TypeIds, "TypeId", "Name");
-- View
#* ??? Get the name by a local #id *#
<div>ViewBag.TypeId.SelectItemNameById(#id)</div> #* Bad psuedo code here... *#
I will use Jquery with an ajax call on the onChange of your dropdownlist.
$(document).ready(function () {
$("#MyDrop").change(function () { GetValue("#MyDrop"); });
});
function GetValue(objSource) {
var url = '/Home/Index/GetValue/';
$.getJSON(url, { id: $(objSource).val() }, function (data) {
//with data returned fill your fields
});
});
}
From the controller
public ActionResult GetValue(string id)
{
int intId = 0;
int.TryParse(id, out intId);
var myData = //Get the value from Id
return Json(myData, JsonRequestBehavior.AllowGet);
}
Remeber to use AllowGet if you don't do a Post call from your ajax (like in my example)
UPDATE to reflect the comments
To achive what you need use a Dictionary passed via ViewBag.
Then from your view you access the (Dictionary)ViewBag.MyDictionary.
Or whatever collection you prefer.

Resources