Kendo Ui DataSource Add Function not working properly - kendo-ui

I defined a Kendo Data Source as below. It is populating values in a ListView.
var datasourceAppList = new kendo.data.DataSource({
transport: {
create: function(options){
//alert(options.data.desc);
alert(options.data.desc);
var localData = JSON.parse(localStorage.getItem("LsAppList"));
localData.push(options.data);
localStorage.setItem("LsAppList", JSON.stringify(localData)); //localStorage["LsAppList"] = JSON.stringify(localData);
options.success(localData);
},
read: function(options){
var localData = JSON.parse(localStorage["LsAppList"]);
options.success(localData);
},
update: function(options){
var localData = JSON.parse(localStorage["LsAppList"]);
for(var i=0; i<localData.length; i++){
if(localData[i].extappId == options.data.extappId){
localData[i].desc = options.data.desc;
localData[i].deviceNo = options.data.deviceNo;
localData[i].validationKey = options.data.validationKey;
}
}
localStorage["grid_data"] = JSON.stringify(localData);
options.success(localData);
},
destroy: function(options){
var localData = JSON.parse(localStorage["LsAppList"]);
localData.remove(options.data.ID);
localStorage["LsAppList"] = JSON.stringify(localData);
options.success(localData);
},
},
schema: {
model: {
extappId: "ID",
fields: {
extappId: { type: "number" },
desc: { type: "string" },
deviceNo: { type: "number" },
validationKey: { type: "string" }
}}
},
});
First : I call the following code. it adds the data correctly both to te page listview and localStorage.
datasourceAppList.add({ extappId: "9905", desc: "test", deviceNo: "5", validationKey: "CACACACA"});
datasourceAppList.sync();
Second: I call the folowing code
datasourceAppList.add({ extappId: "9908", desc: "harvest", deviceNo: "7", validationKey: "ppppppp"});
datasourceAppList.sync();
Problems:
the page is showing the first record twice.
The localstorage has 2 times the first record and 1 time the second record.
what am I doing wrong?
--- one problem still exists. though the localStorage is correct, the listview is populating wrong.
First Record Add : ListView is Correct
Second Record Add : ListView is Corract
Third Record Add : First 2 lines shows the first record and the last line shows the last record.
My HTML code is
<div id="applications" data-role="view" data-title="Defined Applications" data-layout="default" data-model="appdetail">
<ul id="applist" data-role="listview" data-style="inset" data-source="datasourceAppList" data-template="tmp" data-click="listViewClick" data-auto-bind="true"></ul>
<p align="center">
<a style="width: 30%" data-role="button" data-rel="modalview" data-click="showModalViewAdd" id="buttonAddApplication" data-icon="ecg-plus">Add</a>
<a style="width: 30%" data-role="button" data-rel="modalview" data-click="refreshApplicationList" id="buttonRefreshApplication" data-icon="refresh">Refresh</a>
</p>
</div>
<script id="tmp" type="text/x-kendo-template">
<a id = "#: extappId #">#: desc # </a>
</script>

It is actually a combined problem:
You schema definition is:
schema: {
model: {
extappId: "ID",
fields: {
extappId: { type: "number" },
desc: { type: "string" },
deviceNo: { type: "number" },
validationKey: { type: "string" }
}
}
}
It says extappId: "ID"... what is this? Do you want to say that extappId is the id of that record? If so, the actual definition should be:
schema: {
model: {
id: "extappId",
fields: {
extappId: { type: "number" },
desc: { type: "string" },
deviceNo: { type: "number" },
validationKey: { type: "string" }
}
}
}
What happens here is not being (correctly) defined the id, KendoUI expects that id is actually id and since this is not being set during the create next time that you sync it tries to save it, it is equivalent to:
datasourceAppList.add({ extappId: 9905, desc: "test", deviceNo: 5, validationKey: "CACACACA"});
datasourceAppList.add({ extappId: 9908, desc: "harvest", deviceNo: 7, validationKey: "ppppppp"});
datasourceAppList.sync();
But if you try this, you will see that then create is never invoked. Now what happens is that the id of the record (i.e. extappId) is already defined and not null and so KendoUI believes that is already saved.
For solving this second issue my recommendation is defining the schema as:
schema: {
model: {
id: "ID",
fields: {
extappId: { type: "number" },
desc: { type: "string" },
deviceNo: { type: "number" },
validationKey: { type: "string" }
}
}
}
Now, the id is a field called ID and this ID should be created on transport.create (cannot be set before invoking add method).
Then, you set it in create and you can use:
create: function(options){
// Set `ID` to kendo.guid
options.data.ID = kendo.guid();
alert(options.data.desc);
var localData = JSON.parse(localStorage.getItem("LsAppList"));
localData.push(options.data);
localStorage.setItem("LsAppList", JSON.stringify(localData)); //localStorage["LsAppList"] = JSON.stringify(localData);
options.success(localData);
},
Check it here : http://jsfiddle.net/OnaBai/n7sNd/3/

Related

How to get field value when edit data in Kendo Ui treelist

I'm new in Kendo UI,and i have a question. Now i'm use TreeList / Editing and how to auto load value to other field when i edit value to first field ?
example:
1.serial number: 123456789
2.name : test
when i edit serial number 123456789 to first field and auto load name to second field.
To set the value of column B based on change made to a column A, you need to edit the model bound to the tree list. For this do the following:-
Handle edit event of the tree list. On this save the model to a
local variable.
Add an editor
template
to column A. On the select event set the value of model.
Below is a working code snippet:-
<div id="treelist"></div>
<script>
$(document).ready(function () {
var crudServiceBaseUrl = "https://demos.telerik.com/kendo-ui/service";
var model= null;
var employeesData=[{"EmployeeId":101,"FirstName":"Daryl","LastName":"Sweeney"},
{"EmployeeId":202,"FirstName":"Guy","LastName":"Wooten"},
{"EmployeeId":303,"FirstName":"Priscilla","LastName":"Frank"},
{"EmployeeId":404,"FirstName":"Ursula","LastName":"Holmes"},
{"EmployeeId":505,"FirstName":"Anika","LastName":"Vega"}];
var dataSource = new kendo.data.TreeListDataSource({
transport: {
read: {
url: crudServiceBaseUrl + "/EmployeeDirectory/All",
dataType: "jsonp"
},
update: {
url: crudServiceBaseUrl + "/EmployeeDirectory/Update",
dataType: "jsonp"
},
destroy: {
url: crudServiceBaseUrl + "/EmployeeDirectory/Destroy",
dataType: "jsonp"
},
create: {
url: crudServiceBaseUrl + "/EmployeeDirectory/Create",
dataType: "jsonp"
},
parameterMap: function(options, operation) {
if (operation !== "read" && options.models) {
return {models: kendo.stringify(options.models)};
}
}
},
batch: true,
schema: {
model: {
id: "EmployeeId",
parentId: "ReportsTo",
fields: {
EmployeeId: { type: "number", nullable: false },
ReportsTo: { nullable: true, type: "number" },
FirstName: { validation: { required: true } },
HireDate: { type: "date" },
Phone: { type: "string" },
HireDate: { type: "date" },
BirthDate: { type: "date" },
Extension: { type: "number", validation: { min: 0} },
Position: { type: "string" }
},
expanded: true
}
}
});
$("#treelist").kendoTreeList({
dataSource: dataSource,
toolbar: [ "create", "save", "cancel" ],
editable: "incell",
height: 540,
dataBound: function (e) {
var items = e.sender.items();
for (var i = 0; i < items.length; i++) {
var dataItem = e.sender.dataItem(items[i]);
var row = $(items[i]);
if (dataItem.isNew()) {
row.find("[data-command='createchild']").hide();
}
else {
row.find("[data-command='createchild']").show();
}
}
},
edit: function(e) {
model = e.model;
},
columns: [{
field: "EmployeeId",
expandable: true,
title: "Serial Number",
width: 180,
editor: function(container, options) {
// create an input element
var input = $("<input/>");
// set its name to the field to which the column is bound ('lastName' in this case)
input.attr("name", options.field);
// append it to the container
input.appendTo(container);
// initialize a Kendo UI AutoComplete
input.kendoAutoComplete({
dataTextField: "EmployeeId",
dataSource: employeesData,
select: function(e) {
if(model !=null){
model.FirstName = e.dataItem.FirstName;
model.LastName = e.dataItem.LastName;
}
}
});
}
},
{ field: "FirstName", title: "First Name", width: 100 },
{ field: "LastName", title: "Last Name", width: 100 },
{ field: "Position", width: 100 },
{ field: "Phone", title: "Phone", width: 100 },
{ field: "Extension", title: "Ext", format: "{0:#}", width: 100 },
{ command: [{name: "createchild", text: "Add child"},"destroy" ], width: 240 }]
});
});
</script>
You can trigger your function when the row is being saved or when the edit field is being changed. Take a look at the list of events here and choose when exactly you want to make the changes. https://demos.telerik.com/kendo-ui/treelist/events
here is a example how to all a function when saving the changes: https://docs.telerik.com/kendo-ui/api/javascript/ui/treelist/methods/saverow
I´m not sure witch edit method you are using (inline, inCell or Popup edit mode) each method can use events like saveRow, beforeEdit...
Check all the events documentation here: https://docs.telerik.com/kendo-ui/api/javascript/ui/treelist#events

How to allow kendo grid to bind to an undefined field

I have this json object
{
id: string,
name: string,
category: {
id: string
name: string,
}
}
I want to have column that bind to productCategory.name. However that field is nullable. When productCategory is null/undefined, kendo will throw error. How can i tell kendo that if field is undefined, just show empty string?
EDIT
Below is my sample data
[{
"id":1,
"name":"Spaghetti",
"category":{
"id":"1",
"name":"Food"
}},
{
"id":2,
"name":"Coca-cola",
"category":null
}}]
Below is my kendo datasource
var kendoDataSource = new kendo.data.DataSource({
schema: {
data: "data",
total: "total",
model: {
id: "id",
fields: {
id: { type: "string" },
name: { type: "string" },
"category.name": { type: "string" }
}
}
}
});
Data above will throw "undefined" error, because second product does not have category.
Try using empty object instead of null
created a fiddle,check this:
http://jsfiddle.net/Sowjanya51/h930jcru/
Just provide a default value in your model like this:
var kendoDataSource = new kendo.data.DataSource({
schema: {
data: "data",
total: "total",
model: {
id: "id",
fields: {
id: { type: "string" },
name: { type: "string" },
"category.name": { type: "string" },
category: { defaultValue: {
id: "",
name: "",
}
}
}
}
}
});
This will initialize productCategory if it is null or undefined.

Saving a Kendo datasource using jStorage

I'm adding and removing data to a Kendo dataSource. I wish to save it localStorage, and be able to read it again from localStorage.
Here I've attempted to use jStorage for the saving and loading of data.
How it's loaded:
if ($.jStorage.get('favoritter') != null) {
var datakilde_favoritter = $.jStorage.get('favoritter');
} else {
var data = [
{id: 5, name: "LINK ONE", url: "http://www.linkone.com" }
];
var datakilde_favoritter = new kendo.data.DataSource({
data: data,
sort: { field: "name", dir: "asc" }
});
}
How it's saved:
$.jStorage.set('favoritter', datakilde_favoritter);
Define your DataSource as:
var ds = new kendo.data.DataSource({
transport: {
read : function (op) {
var data = $.jStorage.get('favoritter');
if (!data) {
data = [
{id: 5, name: "LINK ONE", url: "http://www.linkone.com" }
];
}
op.success(data);
},
update : function (op) {
$.jStorage.set("favoritter", ds.data());
op.success(op.data);
},
destroy: function (op) {
console.log("destroy", ds.data());
$.jStorage.set("favoritter", ds.data());
op.success(op.data);
},
create : function (op) {
$.jStorage.set("favoritter", ds.data());
op.success(op.data);
}
},
sort : { field: "name", dir: "asc" },
pageSize : 10,
schema : {
model: {
id : "id",
fields: {
id : { type: 'number' },
name: { type: 'string' }
}
}
}
});
You might consider removing create and destroy if not needed.
And your grid would be something like:
var grid = $("#grid").kendoGrid({
dataSource: ds,
editable : "popup",
pageable : true,
toolbar : ["create"],
columns : [
{ command: ["edit", "destroy"], width: 100 },
{ field: "id", width: 90, title: "#" },
{ field: "name", width: 90, title: "URL Name" }
]
}).data("kendoGrid");
Basically when updating you need to invoke op.success with the data returned from the server. In your case since it is the browser itself, you don't need just to return the original data.

Problems with Kendo UI Grid Editing

I tried use the Kendo Grid and i found some problems.
The button action "edit" and "remove " do nothing when i click, but if i put the "create" command into the transport, the grid send lots of POSTS for the create URL command when i click in delete or click in edit > cancel (the update button do nothing too).
What I doing wrong?
My code:
<div id="grid"></div>
<script type="text/x-kendo-template" id="template">
<div class="toolbar">
<input type="number" min="0" id="item-id" maxlength="10" />
<input type="text" id="name" class="k-textbox" placeholder="..." />
<button style="width: 100px" id="btn-grid-filtrar" class="k-button" >Filter</button>
</div>
</script>
<script>
$(document).ready(function() {
var dataSource = new kendo.data.DataSource(
{
schema:
{
data: "data",
total: "total",
model:
{
id: "data",
fields:
{
id: { editable: false, nullable: false },
nome: { type: "string", validation: { required: true} },
ativo: { type: "boolean" }
}
}
},
transport:
{
read:
{
url: "page",
dataType: "json",
type: "POST",
data: additionalData
},
update: {
url: "update",
dataType: "jsonp"
},
destroy: {
url: "delete",
dataType: "jsonp"
}
/*,
create: {
url: "add",
dataType: "jsonp"
}
*/
},
pageSize: 5,
serverSorting: true,
serverPaging: true,
});
var grid = $("#grid").kendoGrid({
dataSource: dataSource,
sortable: true,
pageable: {
input: true,
numeric: false
},
batch: true,
columns: [
{ field: "id", title: "#", width: "60px" },
{ field: "nome", title: "Nome" },
{ field: "ativo", title: "Ativo", width: "60px", template: "#= ativo ? 'Sim' : 'Não' #" },
{ command: ["edit", "destroy"], title: "Ações", width: "200px" }
],
editable: "inline",
toolbar: kendo.template($("#template").html()),
});
kendo.bind($(".toolbar"));
$("#id").kendoNumericTextBox({
format: "##########",
placeholder: "..."
});
$("#btn-grid-filtrar").click(function() {
grid.data("kendoGrid").dataSource.read();
});
});
function additionalData() {
return {
filtro_id: $("#item-id").val(),
filtro_nome: $("#name").val()
};
}
</script>
First of all, I'm assuming that you server is serving a JSON with the following format:
{
"total": 2,
"data" : [
{
"data" : 23,
"id" : 1,
"ativo": true,
"nome" : "stock-1"
},
{
"data" : 34,
"id" : 2,
"ativo": false,
"nome" : "stock-2"
}
]
}
Correct?
So the first thing is changing the "data" on each row data to something not called data. It turns out that data is a kind-of reserved word in KendoUI commonly used in code structures as:
with (data) {
// Expanded code coming from a grid row data
}
Where this data is a variable referencing a row in your grid. So, in this context data is both the row itself and and a field in that row and then JavaScript cannot correctly solve it.
So you can define your schema as:
schema : {
data : "data",
total: "total",
model: {
id : "_data",
fields: {
id : { editable: false, nullable: false },
nome : { type: "string", validation: { required: true} },
ativo: { type: "boolean" }
}
}
},
NOTE: I've replace data by _data.
Transmitted data is:
{
"total": 2,
"data" : [
{
"_data" : 23,
"id" : 1,
"ativo": true,
"nome" : "stock-1"
},
{
"_data" : 34,
"id" : 2,
"ativo": false,
"nome" : "stock-2"
}
]
}
Just with this small change your Edit button will start working.
You are not supposed to define transport level for local datasources, if understand correctly your code, you are not posting anywhere - you are not binding any remote data, I can't see any url ? Follow this example http://demos.kendoui.com/web/datasource/index.html.

Display the popup view when the filtering is under process

In my group's project, we had a one grid and export button. We came across an issue which is that when exopt the data in excel format fiddle: http://jsfiddle.net/SZBrt/11/ need to display the pop up message stating that 'The data is getting filtered' to be displayed so that the we can know the filtering is under process. I appreciate your help in advance.
And My Code:
var grid = $("#grid").kendoGrid({
dataSource: {
type : "odata",
transport : {
read: "http://demos.kendoui.com/service/Northwind.svc/Orders"
},
schema : {
model: {
fields: {
OrderID : { type: "number" },
Freight : { type: "number" },
ShipName : { type: "string" },
OrderDate: { type: "date" },
ShipCity : { type: "string" }
}
}
},
pageSize : 10
},
filterable: true,
sortable : true,
pageable : true,
columns : [
{
field : "OrderID",
filterable: false
},
"Freight",
{
field : "OrderDate",
title : "Order Date",
width : 100,
format: "{0:MM/dd/yyyy}"
},
{
field: "ShipName",
title: "Ship Name",
width: 200
},
{
field: "ShipCity",
title: "Ship City"
}
]
}).data("kendoGrid");
Add to the DataSource definition an event handler for requestStart and requestEnd.
dataSource: {
requestStart : function() {
// Add code for displaying your own "loading" message
},
requestEnd: function() {
// Add code for hiding your own "loading" message
},
type : "odata",
transport : {
read: "http://demos.kendoui.com/service/Northwind.svc/Orders"
},
schema : {
model: {
fields: {
OrderID : { type: "number" },
Freight : { type: "number" },
ShipName : { type: "string" },
OrderDate: { type: "date" },
ShipCity : { type: "string" }
}
}
},
pageSize : 10
},
You did not specify how that Loading message looks like, it might be as simple as adding / removing visibility:
requestStart: function () {
$("#loading-msg").css("visibility", "visible");
},
requestEnd: function () {
$("#loading-msg").css("visibility", "hidden");
},
or open / close a window:
requestStart: function () {
$("#loading-msg").data("kendoWindow").center().open();
},
requestEnd: function () {
$("#loading-msg").data("kendoWindow").close();
},

Resources