Kendo UI - DataSource works when using fetch(), but not read() - kendo-ui

I have a Kendo UI DataSource that works when I use fetch(), but when I use the exact same configurtation with read() it fails. This is a problem as I need to retrieve data more than once and I can't do that with fetch().
Here is the DataSource code -
var FieldsDataSource = new kendo.data.DataSource({
transport: {
read: {
url: "../WebServiceAddress",
dataType: "json",
type: "POST",
contentType: 'application/json; charset=utf-8',
cache: false
},
parameterMap: function() {
return "{some mapping that has been confirmed to work}";
},
schema: {
data: function (data) {
if (data && data.d) {
//execution gets to here and stops
return data.d;
}
else {
return [];
}
},
}
});
Here is the code that calls the DataSource.read() function -
function loadFields() {
FieldsDataSource.read(function() {
var data = this.data();
if (data.length > 0) {
for (var i = 0; i < data.length; i++) {
var dataitem = data[i].Key;
$("#" + dataitem + "_field").prop("checked", data[i].Value);
}
}
});
}
If I change FieldsDataSource.read(function() to FieldsDataSource.fetch(function() everything works, but that doesn't make sense as I was under the improession that read and fetch do the same thing the difference being fetch only gets data once.
What I do know is that the data is being returned from the server, I can see it in fiddler - but the execution stops in the schema section where I flagged it in my code sample.
Apologies if I am asking a really obvious question, but I'm very new to Kendo.

have a look at the kendo demo site, this post explains how to read remote data quite nicely. I beleive the schema.data requires only string value. Configure your model and parse and then just call read(), your datasource.data collection will get populated and then you can play with it.
Also note that datasource.read() is async, thefore you populatefields method should be called from complete event of the datasource, not other way around. eg you might have no data in when populating.
transport: {
read: {
url: "../WebServiceAddress",
dataType: "json",
type: "POST",
contentType: 'application/json; charset=utf-8',
cache: false,
complete : function () { }
},

Related

call function in ajax success callback

Is it possible to call a function in success callback of ajax request?
For example I have something like that :
constructor(private http: HttpClient,private serviceComposition: CompositionService) { }
[...]
save() {
var isValid = this.isValidCompo();
if (true) {
var toSend = JSON.stringify(this.setupComposition);
$.ajax({
url: "/api/setup/composition/addSetupComposition",
type: 'POST',
dataType: "json",
data: 'setupComposition=' + toSend,
success:function(response){
//console.log("Success Save Composition");
},
error: function(XMLHttpRequest,textStatus,errorThrown){
console.log("Error Save Compo");
}
}).done(function(data){
this.serviceComposition.changeValue(isValid);
})
}
}
I want to call a function of my service (named : changeValue() ) if my ajax request is a success.
But I have this error message : core.js:12632 ERROR TypeError: Cannot read property 'changeValue' of undefined
Do you know if it's possible to resolve that ?
I am suspecting this binding is going wrong in call backs,
prefer using arrow function because of "this" operator binding.
if (true) {
var toSend = JSON.stringify(this.setupComposition);
$.ajax({
url: "/api/setup/composition/addSetupComposition",
type: 'POST',
dataType: "json",
data: 'setupComposition=' + toSend,
success:function(response){
//console.log("Success Save Composition");
},
error: function(XMLHttpRequest,textStatus,errorThrown){
console.log("Error Save Compo");
}
}).done((data) => {
this.serviceComposition.changeValue(isValid);
})
}
if not u can store this reference in a variable and call it
var self = this;
if (true) {
var toSend = JSON.stringify(this.setupComposition);
$.ajax({
url: "/api/setup/composition/addSetupComposition",
type: 'POST',
dataType: "json",
data: 'setupComposition=' + toSend,
success:function(response){
//console.log("Success Save Composition");
},
error: function(XMLHttpRequest,textStatus,errorThrown){
console.log("Error Save Compo");
}
}).done(function(data){
self.serviceComposition.changeValue(isValid);
})
}
Use an arrow function to access this of your parent scope. In your example, this is referring to your jQuery XHR object.
So:
// [parent scope]
$.ajax({
...
}).done((data) => {
// [child scope]
// `this` now refers to [parent scope], so the following is valid
this.serviceComposition.changeValue(isValid);
});
Another common practice prior to arrow functions (ES6) would've been assigning a const self = this; variable in the [parent scope] area to be accessed in the child method. Either method works the same.
Also check out the MDN docs on this. It's a confusing topic for many.

Kendo get data from remote service, do paging locally

Code:
var url = base_url + "/api/v1/users/getUsers";
var dataSource = new kendo.data.DataSource({
transport: {
read: function (options) {
$.ajax({
type: 'GET',
url:url,
dataType: 'json',
data: { searchTerm: $("#searchTerm").val().trim() },
success: function (result) {
options.success(result);
},
error: function (result) {
options.error(result);
}
});
}
},
schema: {
data: function (result) {
return result.model;
},
total: function (result) {
return result.model.length;
},
},
pageSize: 5
});
$("#matches").kendoListView({
dataSource: dataSource,
autoBind: false, // if set to false the widget will not bind to the data source during initialization.
template: kendo.template($("#matchesListViewTemplate").html())
});
$("#pager").kendoPager({
dataSource: dataSource,
autoBind: false
});
$(document).keypress(function (e) {
if (e.which == 13) {
e.preventDefault();
var searchTerm = $("#searchTerm").val().trim();
if (searchTerm.length < 1)
return;
dataSource.read();
dataSource.page(1); // makes another call to the remote service
}
});
Because data source is remote, when we call dataSource.page(1), kendo issues another call to the remote service. This behaviour is described in this so post:
If you are doing server side paging it should be enough doing grid.dataSource.page(1) since this will invoke the read exactly as you already realized.
What must I change so that after I search with new searchTerm, API call would be done only once and pager would go to page 1 without making another call?
I tried with dataSource.query() but still no luck? I hope I demonstrated enough.
Solution is to call dataSource.page(1) when dataSource.read() gets data / is done.
$(document).keypress(function (e) {
if (e.which == 13) {
e.preventDefault();
var searchTerm = $("#searchTerm").val().trim();
if (searchTerm.length < 1)
return;
dataSource.read().done(function() {
// in case remote service returns empty result set (but still http 200 code)
// page() makes another request (if data() is empty it makes another request)
// therefore we must check data length/total
if( dataSource.total() > 0)
dataSource.page(1);
}
});
If the read request's response have not arrived yet or if an error occurs, another read request is allowed (in order to fetch data). DataSource.read() makes asynchronously request and then dataSource.page(1) starts to execute. DataSource.page(1) function checks if there is any data read, if it's not it executes again read method - therefore we got 2 calls as you mentioned it. Because of asynchronously call this scenario may happen.

Kendo Datasource Transport custom function not getting called

Im experiencing a rather annoying bug (?) in Kendo UI Datasource.
My Update method on my transport is not getting called when I pass a custom function, but it does work if I just give it the URL.
This works:
...
transport: {
update: { url: "/My/Action" }
}
...
This does not
...
transport: {
update: function(options) {
var params = JSON.stringify({
pageId: pageId,
pageItem: options.data
});
alert("Update");
$.ajax({
url: "/My/Action",
data:params,
success:function(result) {
options.success($.isArray(result) ? result : [result]);
}
});
}
}
...
The function is not getting invoked, but an ajax request is made to the current page URL, and the model data is being posted, which is rather odd. Sounds like a bug to me.
The only reason I have a need for this, is because Kendo can't figure out that my update action returns only a single element, and not an array - so, since I dont want to bend my API just to satisfy Kendo, I though I'd do it the other way around.
Have anyone experienced this, and can point me in the right direction?
I also tried using the schema.parse, but that didn't get invoked when the Update method was being called.
I use myDs.sync() to sync my datasource.
Works as expected with the demo from the documentation:
var dataSource = new kendo.data.DataSource({
transport: {
read: function(options) {
$.ajax( {
url: "http://demos.kendoui.com/service/products",
dataType: "jsonp",
success: function(result) {
options.success(result);
}
});
},
update: function(options) {
alert(1);
// make JSONP request to http://demos.kendoui.com/service/products/update
$.ajax( {
url: "http://demos.kendoui.com/service/products/update",
dataType: "jsonp", // "jsonp" is required for cross-domain requests; use "json" for same-domain requests
// send the updated data items as the "models" service parameter encoded in JSON
data: {
models: kendo.stringify(options.data.models)
},
success: function(result) {
// notify the data source that the request succeeded
options.success(result);
},
error: function(result) {
// notify the data source that the request failed
options.error(result);
}
});
}
},
batch: true,
schema: {
model: { id: "ProductID" }
}
});
dataSource.fetch(function() {
var product = dataSource.at(0);
product.set("UnitPrice", product.UnitPrice + 1);
dataSource.sync();
});
Here is a live demo: http://jsbin.com/omomes/1/edit

kendo grid custom delete not persisting to datasource

I simply want to use my own workflow for deleting a record from my grid. Is this not the proper way to do it via Javascript? The function below removes the row but refreshing the page shows the row was not actually deleted from the datasource and I do not see any requests sent in the network tab of Chrome. I should add that I am able to obtain a reference to the grid and the dataItem perfectly.
function delete(e) {
var $tr = $(e.currentTarget).closest("tr"),
grid = this,
dataItem = grid.dataItem($tr),
id = $tr.attr(kendo.attr("uid")),
model = grid.dataSource.getByUid(id);
e.preventDefault();
grid.dataSource.remove(model);
grid.dataSource.sync();
}
Edit - Here is how my datasource is defined:
$scope.contacts = new kendo.data.DataSource({
transport: {
read: {
url: apiUrl,
dataType: "json",
type: "GET"
},
update: {
url: apiUrl,
dataType: "json",
type: "POST"
},
destroy: {
url: apiUrl,
type: "DELETE"
},
create: {
url: apiUrl,
dataType: "json",
type: "POST"
}
},
pageSize: 10
});
I found something and I dont know if it works in your side.
I needed to add this line in my kendo.datasource
schema: {
model:{id:"id"}
}
and trigger like this
data_source_inspection.remove(selected.data);
data_source_inspection.sync();
this works for me.

jquery autocomplete using mvc3 dropdownlist

I am using ASP.NET MVC3 with EF Code First. I have not worked previously with jQuery. I would like to add autocomplete capability to a dropdownlist that is bound to my model. The dropdownlist stores the ID, and displays the value.
So, how do I wire up the jQuery UI auto complete widget to display the value as the user is typing but store the ID?
I will need multiple auto complete dropdowns in one view too.
I saw this plugin: http://harvesthq.github.com/chosen/ but I am not sure I want to add more "stuff" to my project. Is there a way to do this with jQuery UI?
Update
I just posted a sample project showcasing the jQueryUI autocomplete on a textbox at GitHub
https://github.com/alfalfastrange/jQueryAutocompleteSample
I use it with regular MVC TextBox like
#Html.TextBoxFor(model => model.MainBranch, new {id = "SearchField", #class = "ui-widget TextField_220" })
Here's a clip of my Ajax call
It initially checks its internal cached for the item being searched for, if not found it fires off the Ajax request to my controller action to retrieve matching records
$("#SearchField").autocomplete({
source: function (request, response) {
var term = request.term;
if (term in entityCache) {
response(entityCache[term]);
return;
}
if (entitiesXhr != null) {
entitiesXhr.abort();
}
$.ajax({
url: actionUrl,
data: request,
type: "GET",
contentType: "application/json; charset=utf-8",
timeout: 10000,
dataType: "json",
success: function (data) {
entityCache[term] = term;
response($.map(data, function (item) {
return { label: item.SchoolName, value: item.EntityName, id: item.EntityID, code: item.EntityCode };
}));
}
});
},
minLength: 3,
select: function (event, result) {
var id = result.item.id;
var code = result.item.code;
getEntityXhr(id, code);
}
});
This isn't all the code but you should be able to see here how the cache is search, and then the Ajax call is made, and then what is done with the response. I have a select section so I can do something with the selected value
This is what I did FWIW.
$(document).ready(function () {
$('#CustomerByName').autocomplete(
{
source: function (request, response) {
$.ajax(
{
url: "/Cases/FindByName", type: "GET", dataType: "json",
data: { searchText: request.term, maxResults: 10 },
contentType: "application/json; charset=utf-8",
success: function (data) {
response($.map(data, function (item) {
return {
label: item.CustomerName,
value: item.CustomerName,
id: item.CustomerID
}
})
);
},
});
},
select: function (event, ui) {
$('#CustomerID').val(ui.item.id);
},
minLength: 1
});
});
Works great!
I have seen this issue many times. You can see some of my code that works this out at cascading dropdown loses select items after post
also this link maybe helpful - http://geekswithblogs.net/ranganh/archive/2011/06/14/cascading-dropdownlist-in-asp.net-mvc-3-using-jquery.aspx

Resources