Kendo Datasource response is empty - kendo-ui

I am new to Kendo UI. I am trying to read the remote data and display in the screen. I am able to see the remote json data by accessing the URL in the browser. But when I try to alert() the response data inside kendo UI, it is empty.
here is the sample code.
<script type="text/javascript">
var shareDataSource;
var viewModel;
function searchByVin() {
var vin = $("#vinNumber").val();
shareDataSource = new kendo.data.DataSource({
transport: {
read: {
url: "http://localhost:9080/portal/programexcep/resources/request/vin/"+vin,
dataType: "json"
}
},
schema: {
data: "data",
model: { id: "Id" }
},
requestEnd: function(e) {
var response = e.response;
var type = e.type;
alert(type);
alert(response.length);
}
});
shareDataSource.read();
alert(vin);
alert(kendo.stringify(shareDataSource.data()));
}
</script>
The JSON data is
{"Id":10,"FirstName":"John Smith","vin":"html5"}
as the response in the browser. The alert(kendo.stringify(shareDataSource.data())); is empty
and the alert(response.length); is also undefined.
Can someone help on this?

The problem is that shareDataSource.read(); is asynchronous which means that you invoke read but data is not immediately available. You can use fetch instead that executes a portion of code when the data is available. Your code would be:
shareDataSource.fetch(function() {
alert(vin);
alert(kendo.stringify(shareDataSource.data()));
});
There is also a problem in requestEnd function: you try to get the length of response but in the model definition you say that data field is called data so your server should be returning something like:
{
"data" : [
{ "Id" : 1 },
{ "Id" : 2 },
{ "Id" : 3 }
]
}
and then for accessing the length you should do response.data.length

Related

How to reload datatable by using new url and some parameters without reinitialize it

I know I can make ajax request on datatable using ajax.url like this :
var table = $('#example').DataTable( {
ajax: "/mylink"
} );
...
table.ajax.url( 'newData.json' ).load();
But how can I pass data as parameters to url using the same syntax?
I try table.ajax.url( 'mylink' ).data(myData).load(); . Obsviouly it is not solution.
I do not want to destroy and reinitialize the datatable in order to use :
...
"ajax" : {
"url" : "mylink",
"data" : myData
}
...
What do I do? What is the syntax using existing initialized table (here js var table)?
thanks
In your DataTables ajax section, instead of using the object form of the data option, you can use the function form. This allows you to dynamically pass in your request data for each new ajax call.
So, instead of this:
"data" : myData
It would be this:
"data": function () {
return myData;
}
And, as you already note, you can use the ajax.url() call to specify the new URL:
table.ajax.url( 'newData.json' ).load();
Warning: This assumes you are not using server-side processing, as this will overwrite the server-side request data which is auto-generated by DataTables. If you are using server-side processing, then you have to merge your custom data into the pre-existing request data.
The documentation shows an example for that, using jQuery extend:
"data": function ( d ) {
return $.extend( {}, d, {
"extra_search": $('#extra').val()
} );
}
You don't need to use $.extend. You just need to be careful that you do not overwrite the request data generated by Datatables.
Another way to handle this is to simply append data to the data structure represented by d in "data": function ( d ):
"data": function ( d ) {
d.extra_search = $('#extra').val();
}
Update with a more detailed example
Here is a full example, which you can copy into a html file and run for yourself, if you wish. It uses data from a dummy JSON provider, just for testing.
The HTML, showing the table and a button. The button is how I tested the ability to call a new URL and pass new request parameters to that new URL:
<div style="margin: 20px;">
<button id="button_one" type="button">Resubmit</button>
<br><br>
<table id="example" class="display" style="width:100%"></table>
</div>
Here is the related script containing the DataTable definition and a function which calls the new URL (with new request parameters):
<script>
$(document).ready(function() {
// ajax for initial table creation:
var requestUrl = "https://jsonplaceholder.typicode.com/posts";
var requestData = { "name": "Abel", "location": "here" };
var table = $('#example').DataTable( {
ajax: {
method: "GET",
url: requestUrl,
"data": function ( ) {
return requestData;
},
dataSrc: "",
},
"columns": [
{ "title": "User ID", "data": "userId" },
{ "title": "ID", "data": "id" },
{ "title": "Title", "data": "title" }
]
} );
$("#button_one").click(function() {
// subsequent ajax call, with button click:
requestUrl = "https://jsonplaceholder.typicode.com/todos";
requestData = { "name": "Charlie", "location": "there" };
table.ajax.url( requestUrl ).load();
});
} );
</script>
The key points in this example are:
There are 2 different URLs. The first one is used when DataTables is created. The second one is used when the button is clicked.
There are 2 different sets of request data, for the two URLs.
Using this approach, you can repeatedly call table.ajax.url( requestUrl ).load() with different URLs and different sets of request data, without needing to destroy the DataTable.
Handling Form Data
Here is a simple HTML form:
<form id="filter-form">
City:<input type="text" id="city" name="city">
Country:<input type="text" id="country" name="country">
<input type="submit" value="Submit">
</form>
For testing, I have the following JavaScript which captures the contents of the form into an array:
var form_data = [];
$( "#filter-form" ).submit(function( event ) {
event.preventDefault();
form_data = $( this ).serializeArray();
table.ajax.url( url ).load();
});
The end result is data like this in the form_data variable:
[
{
"name": "city",
"value": "Berlin"
},
{
"name": "country",
"value": "Germany"
}
]
Now I can merge that data into the automatically created server-side request data. This is where I can choose to use the $.extend() function I mentioned above:
$('#example').DataTable( {
serverSide: true,
ajax: {
method: "POST",
url: url, // from a variable
data: function( d ) {
return $.extend( {}, d, { "my_extra_data": form_data } );
}
},
... //whatever else is in your DataTable definition...
});
This function results in request data like the following:
{
"draw": "2",
"columns[0][data]": "id",
"columns[0][name]": "",
...
"start": "0",
"length": "10",
"search[value]": "",
"search[regex]": "false",
"my_extra_data[0][name]": "city",
"my_extra_data[0][value]": "Berlin",
"my_extra_data[1][name]": "country",
"my_extra_data[1][value]": "Germany"
}
You can see your my_extra_data values are included along with the server-side auto-generated request data. And all of this gets sent to the server as part of your request.
If you are using POST then it's in the request body.
If you are using GET, then it's the same data - but added to the URL as a query string.
In both cases, it's converted to the standard string representation used by form data.
It's then up to the server-side code to access this data in the usual way.
NOTE: You may have expected your URL-encoded form data to be provided as this:
...&city=Berlin&country=Germany
But instead it is provided as arrays of name/value pairs:
&my_extra_data%5B0%5D%5Bvalue%5D=Berlin&my_extra_data%5B1%5D%5Bname%5D=country&my_extra_data%5B1%5D%5Bvalue%5D=Germany
So, there is extra server-side work needed to parse this data.
If you want to convert your form data directly into a JavaScript object like this:
{ "city": "Berlin", "country", "Germany" }
then take a look at the answers to this question:
Convert form data to JavaScript object with jQuery

How to change AJAX data in DataTables

I have a DataTable which is able to successfully fetches AJAX data once while initialising the table.Now I need to be able to "refetch" the AJAX data to update the DataTable, but without re-initialising the table.
After some research I found out I need to use the following line "as a function":
ajax.data( data, settings )
Explained here: http://datatables.net/reference/option/ajax.data
However. I cannot find how to use this "as a function". It has not one example on the page.
I tried it as follows.My original DataTable creation:
launch_datatable_ajax = function(){
get_ajax_data();
dyn_t = $('#dynamic_table').DataTable({
"ajax": {
"url":ajax_url,
"data":data,
"dataSrc":""
},
"columns": [
{ "data" : "ID" },
{ "data" : "post_title" },
{ "data" : "supplier_company" },
{ "data" : "img_src" },
{ "data" : "tags" },
{ "data" : "post_meta" },
],
});
}
Then I tried to reload the Data with new parameters. Here's where I'm stuck.
dyn_t.ajax.data(data,dyn_t.settings);
I think I'm correct for the parameters:
dyn_t.settings gives some info on: console.log(dyn_t.settings);
'data' gives my object (the get variables) on: console.log(data);
But console.log says:
Uncaught TypeError: dyn_t.ajax.data is not a function(…)
Reloading can be done with dyn_t.ajax.reload();.
However your requirement is to send updated URL parameters to the server also.
To do this, you need to use the function argument for ajax: http://datatables.net/reference/option/ajax#function
The function re-validates in every ajax.reload() call. This is why the new params will be sent. So assuming you have an HTML form with id my-form, try something like this:
ajax: function ( data, callback, settings ) {
$.ajax({
url: "ajax_url?" + $("my-form").serialize(),
data: { start: data.start, count: data.length }
});
},

JSON encoded improperly when using KendoGrid POST payload

I am binding to a JSON data source, then rebinding after the user initiates a search based on filters on the page. The JSON payload is encoded improperly and nothing I've tried thus far seems to explain why.
If I could just add the correct JSON to the HTTP post, everything would work normally, and does with the $.ajax method listed first.
Using $.ajax call (works)
$.ajax(
{
url: '/api/DataProcessing',
type: "Post",
contentType: "application/json; charset=utf-8",
data: '' + JSON.stringify(searchObject),
dataType: 'json',
success: function (result) {
$(".kendoDataProcessing").data("kendoGrid").dataSource = new kendo.data.DataSource({ data: result });
$(".kendoDataProcessing").data("kendoGrid").dataSource.read();
$(".kendoDataProcessing").data("kendoGrid").refresh();
},
error: function (xhr, ajaxOptions, thrownError) {
alert('Status: ' + xhr.status + ', Error Thrown: ' + thrownError);
}
});
However, when I update the kendogrid data source in what I expect to send an equivalent payload, it encodes the JSON in an unexpected way (see below the code block for before and after HTTP requests captured in Fiddler. (encodes improperly)
$(".kendoDataProcessing").kendoGrid({
dataSource: {
transport: {
read: {
url: '/api/DataProcessing',
type: 'Post',
contentType: 'application/json; charset=utf-8',
data: '' + JSON.stringify(searchObject),
dataType: 'json',
}
},
pageSize: 25
},
height: 620,
sortable: true,
pageable: true,
filterable: true,
columns: [
{
field: "Client",
title: "Client Name",
width: 120
}, {
field: "Study",
title: "Study",
width: 100
}, {
field: "DataLogId",
title: "Batch Description",
width: 120
}, {
field: "Indicator",
title: "Indicator",
width: 100
}, {
field: "UserName",
title: "Username",
width: 110
}, {
field: "AssessmentPoint",
title: "Assessment Point",
width: 130
}, {
field: "DateStamp",
title: "Date Stamp",
width: 180
}]
});
**Expected JSON encoding (HTTP call created using $.ajax method) **
{"Client":"Choose a client...","Study":"Choose a study...","UserName":"Choose a user...","from":"","To":"","AssessmentPoint":"Choose an AP...","Indicator":"Choose an indicator...","DataLogId":""}
**Actual JSON encoding (HTTP call created using Kendogrid data source update and rebind **
0=%7B&1=%22&2=C&3=l&4=i&5=e&6=n&7=t&8=%22&9=%3A&10=%22&11=C&12=h&13=o&14=o&15=s&16=e&17=+&18=a&19=+&20=c&21=l&22=i&23=e&24=n&25=t&26=.&27=.&28=.&29=%22&30=%2C&31=%22&32=S&33=t&34=u&35=d&36=y&37=%22&38=%3A&39=%22&40=C&41=h&42=o&43=o&44=s&45=e&46=+&47=a&48=+&49=s&50=t&51=u&52=d&53=y&54=.&55=.&56=.&57=%22&58=%2C&59=%22&60=U&61=s&62=e&63=r&64=N&65=a&66=m&67 ... (continues)
It looks like it is making the json string into an array of sorts. So I tried with just a test string of "floof" and it encoded to "0=f&1=l&2=o&3=o&4=f"
Controller method called:
public HttpResponseMessage Post([FromBody]DataProcessingSearch dataProcessingSearch)
{
// dataProcessingSearch var is null (was passed oddly encoded)
}
Additional Details (search object)
var searchObject = new Object();
searchObject.Client = $('#ClientList').val();
searchObject.Study = $('#StudyList').val();
searchObject.Site = $('#SiteList').val();
searchObject.UserName = $('#UserList').val();
searchObject.from = $('#beginSearch').val();
searchObject.To = $('#endSearch').val();
searchObject.AssessmentPoint = $('#AssessmentPointList').val();
searchObject.Indicator = $('#IndicatorList').val();
searchObject.DataLogId = $('#DataLogIdText').val();
demo: http://so.devilmaycode.it/json-encoded-improperly-when-using-kendogrid-post-payload
function searchObject(){
return {
Client : $('#ClientList').val(),
Study : $('#StudyList').val(),
Site : $('#SiteList').val(),
UserName : $('#UserList').val(),
from : $('#beginSearch').val(),
To : $('#endSearch').val(),
AssessmentPoint : $('#AssessmentPointList').val(),
Indicator : $('#IndicatorList').val(),
DataLogId : $('#DataLogIdText').val()
}
}
// i have putted the dataSource outside just for best show the piece of code...
var dataSource = new kendo.data.DataSource({
transport: {
read : {
// optional you can pass via url
// the custom parameters using var query = $.param(searchObject())
// converting object or array into query sring
// url: "/api/DataProcessing" + "?" + query,
url: "/api/DataProcessing",
dataType: "json",
// no need to use stringify here... kendo will take care of it.
// also there is a built-in function kendo.stringify() to use where needed.
data: searchObject
},
//optional if you want to modify something before send custom data...
/*parameterMap: function (data, action) {
if(action === "read") {
// do something with the data example add another parameter
// return $.extend({ foo : bar }, data);
return data;
}
}*/
}
});
$(".kendoDataProcessing").kendoGrid({
dataSource: dataSource,
...
});
comments are there just for better explanation you can completely remove it if don't need it. the code is fully working as is anyway.
doc: http://docs.telerik.com/kendo-ui/api/wrappers/php/Kendo/Data/DataSource
What May be the wrong perception:-
1.The Json() method accepts C# objects and serializes them into JSON
strings. In our case we want to return an array of JSON objects; to
do that all you do is pass a list of objects into Json().
public JsonResult GetBooks()
{
return Json(_dataContext.Books);
}
Can you identify what is wrong with the above method? If you didn't already know, the above method will fail at runtime with a "circular reference" exception.
Note: try to return Json, HttpResponse may serialize the data in such a way that it is not acceptable by Kendo Grid. this has happened with me in my project.
Try this Approach:-
Now lets create instances of them in a JsonResult action method.
public JsonResult GetFooBar()
{
var foo = new Foo();
foo.Message = "I am Foo";
foo.Bar = new Bar();
foo.Bar.Message = "I am Bar";
return Json(foo);
}
This action method would return the following JSON:
{
"Message" : "I am Foo",
"Bar" : {
"Message" : "I am Bar"
}
}
In this example we got exactly what we expected to get. While serializing foo it also went into the Bar property and serialized that object as well. However, let's mix it up a bit and add a new property to Bar.
I remember working with a kendo grid in the past. Solution back then was returning jsonp. (needed to work crossdomain not sure if it does in your case)
Suggestion change you controller method to return sjonp by decorating you method with a JsonpFilterAttribute. Something like so:
[JsonpFilter]
public JsonResult DoTheThing(string data, string moreData)
{
return new JsonResult
{
Data = FetchSomeData(data, moreData)
};
}
Then in de Kendo grid try use http://demos.telerik.com/kendo-ui/datasource/remote-data-binding.
For the Jsonpfilter attribute first look at here or else here.

Modify Get Request of a Kendo UI treeview

I'm currently having trouble with my Kendo UI treeview, which essentially displays the same node each time I click it to go deeper into the tree.
My problem is that my regular get request looks like this:
something/GetChildren/3432fdsf8989/Apr222014083453AM
when I click to get the next node the request looks like this:
something/GetChildren/3432fdsf8989/Apr222014083453AM?Identifier=2323eded7664
and I want to have it like this:
something/GetChildren/2323eded7664/Apr222014083453AM
Is it possible to change the URL with a Kendo UI HierarchicalDataSource? My web service is currently Ignoring the Identifier and still using the initial ID.
function initTreeView(date, targetid) {
var requestUrl = "something/GetChildren/"+ targetid + "/" + date;
var dataSource = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url : requestUrl,
dataType : "json"
}
},
schema: {
model: {
id: "Identifier",
hasChildren: true, //all items may have Children
}
}
});
$("#treeview").kendoTreeView({
dataSource: dataSource,
dataTextField: "Message"
});
}
The url in the transport definition can be a function. Define it as a function that generates it in the proper / desired format.
transport: {
read: {
url: function(options) {
return something/GetChildren/"+ targetid + "/" + date;
}
}
}

How to get Single result on kendo.data.Datasource

I have an Odata result like this
{"odata.metadata":"https://localhost/DocTalkMobileWebApiOData/odata/$metadata#MasterPatient/#Element","PatUniqueId":"39e713db-6a0e-4e59-bf7b-033f4fc47ad5", "PatID":null,
"pat_lname":"White","pat_fname":"Peter","pat_mi":" ","pat_ssn":"270787655","pat_dob":"08/07/1973","pat_sex":"M","pat_status":null,"priInsID":2,"secInsID":1,"PCPID":1,"InternalDrID":1,"EXPID":1,"EXPDate":"","pat_phone":null,"isNew":true,"imported":true,"byWhom":"dt","lastUpdate":"2011-03-30T09:41:57.36","changeStamp":"AAAAAAAAIUE=","address":"","city":"","state":"","zip":"","currentMcp":"","currentVisitCount":-2,"otherId":"543674","pcpName":null,"hasChanges":true,"ProgramSource":null,"mrnID":"","createdBy":null,"createdDate":"2007-10-26T10:16:15","expLocation":null,"ethnicId":1,"prefLanguageId":1,"raceId":1
}
and i tried to get this result via kendo.ui.datasource:
newPatient = new kendo.data.DataSource({
type: 'odata', // <-- Include OData style params on query string.
transport: {
read: {
url: url + '/MasterPatient(guid\'00000000-0000-0000-0000-000000000000\')', // <-- Get data from here
dataType: "json" // <-- The default was "jsonp"
},
parameterMap: function (options, type) {
var paramMap = kendo.data.transports.odata.parameterMap(options);
delete paramMap.$inlinecount; // <-- remove inlinecount parameter.
delete paramMap.$format; // <-- remove format parameter.
return paramMap;
}
},
schema: {
data: function (data) {
return data;
},
total: function (data) {
return data['odata.count']
},
}
});
newPatient.fetch(function () {
kendo.bind($('#newPatientTab'), newPatient);
});
But not sure why it always throw error :
Uncaught TypeError: Object [object global] has no method 'slice'
Please help me. Thanks
In Kendo UI, DataSource works only with arrays. If you can change the server response to send something like this
[{"odata.metadata":"https://localhost/DocTalkMobileWebApiOData/odata/$metadata#MasterPatient/#Element","PatUniqueId":"39e713db-6a0e-4e59-bf7b-033f4fc47ad5","PatID":null,"pat_lname":"White","pat_fname":"Peter","pat_mi":" ","pat_ssn":"270787655","pat_dob":"08/07/1973","pat_sex":"M","pat_status":null,"priInsID":2,"secInsID":1,"PCPID":1,"InternalDrID":1,"EXPID":1,"EXPDate":"","pat_phone":null,"isNew":true,"imported":true,"byWhom":"dt","lastUpdate":"2011-03-30T09:41:57.36","changeStamp":"AAAAAAAAIUE=","address":"","city":"","state":"","zip":"","currentMcp":"","currentVisitCount":-2,"otherId":"543674","pcpName":null,"hasChanges":true,"ProgramSource":null,"mrnID":"","createdBy":null,"createdDate":"2007-10-26T10:16:15","expLocation":null,"ethnicId":1,"prefLanguageId":1,"raceId":1}]
then it will work fine.
N.B. It's in array format.
OR
You can wrap the single object into array on the client side, inside data function of the schema.
schema: {
data: function(server-response) {
return [server-response];
}
}
The Kendo team should put more time on good Documentation.
That means you are not using an odata source from the backed. You need to think about here do you really need a kendo odata source from the client in this case if your back-end not supported odata correcly.
See this response from odata url, http://services.odata.org/Northwind/Northwind.svc/?$format=json
It should return an array of object in the value field.
If you can't change the backed what you can do is to format the data in the Schema.data function
schema: {
data: function (data) {
return [data];
},

Resources