Kendo UI dataSource sync on button - kendo-ui

i have kendo ui datasource sync.
Here is the link: http://jsbin.com/uhamer/3/
When you click on list, article will show in grid list(down), then if you click again on same article, it will increse quantity +1.
In that new dataSource that should be synced, schema.model.id is set to id.
When i click on Send data button, it shows me error.
Firebug:
TypeError: r is undefined
Chrome:
Uncaught TypeError: Cannot read property 'data' of undefined
What am i doing wrong here?
Thanks.

I'm not sure if this is part of your error, but with the Kendo UI DataSource it only considers the record to be "new" if its ID column is set to the default (0 since it is a number column). When you copy the row over to the new DataSource you are also copying the ID, so now Kendo thinks that the server already knows about this record since it has an ID.
You can see this by adding a record to your grid's DataSource, then running this JS in the console:
gridNewData.data()[0].isNew(); // returns false because the id column is not 0
When you call .sync() it looks for new records to push to the server but finds none.
You may want to consider having 2 different IDs here; one that is the ID of the Article, and one that is the ID of the DB row (Kendo expects the specified ID column to be the unique DB row ID)
for example:
var gridNewData = new kendo.data.DataSource({
...
schema: {
model: {
id: "id",
fields: {
id: { type: "number" }, // unique DB row ID
articleid: { type: "number" }, // article's ID
name: { type: "string" },
quantity: { type: "number" },
price: { type: "string" }
}
}
}
...
});
Then copy the article's ID into the grid's Article ID:
if (have_in === false) {
gridData.add({
id: 0, // leave this set to 0 or undefined, so Kendo knows it is new.
articleid: addData.id, // copy article's id to new row's articleid
name: addData.name,
quantity: 1,
price: addData.price.toFixed(2),
});
}
I edited your jsbin and you can view it here. Now when the "send data" button is clicked Kendo does a POST of the JSON data:
[{"articleid":1,"name":"Article 1","quantity":2,"price":"20.00","id":0}]
Also note that on the server side, the server should insert this new record into the DB then respond with JSON of the same records but with the "id" set to a non-zero value. For example if the server does a SQL INSERT into a table, that table would probably have some kind of auto generated sequence for the ID column, so if it was created with ID 123, then the server should send an HTTP response with the data:
[{"articleid":1,"name":"Article 1","quantity":2,"price":"20.00","id":123}]
Kendo DataSource will then insepct the HTTP response, fetch that id:123, and update the previously added record in the DataSource to have that id of 123. From that point the record is no longer "new" since its ID is not 0 or undefined, so additional calls to .sync() will not try to send that same record to the server again.
(if the server does not send a response with an id set for the new record, then Kendo will leave the id of the record int he DataSource set to 0, so each time you click "send data" it will keep sending that record over and over)

Related

How do I set a value on a Kendo Observable when it is based on a remote datasource?

I need a default value for a field that I get from a datasource, and bind to that field using an observable. (That value can then be updated if needed by the user using a treeview). I can read the initial remote datasource, build the observable and bind the value to the field. I can then pop up a dialog, show a tree and return the values. What I cant seem to do is set the value of the observable because it is based on a datasource, and therefore seems to be a much bigger and more complicated json object which I am viewing in the console. I have also had to bind differently in order to get that working as well as shown below.
Below if just a snippet, but should give an idea. The remote data source returns just: {"name":"a name string"}
<p>Your default location is currently set to: <span id="repName" data-bind="text: dataSource.data()[0].name"></span></p>
<script>
$(document).ready(function () {
var personSource2 = new kendo.data.DataSource({
schema: {
model: {
fields: {name: { type: "string" }}
}
},
transport: {
read: {
url: "https://my-domain/path/paultest.reportSettings",
dataType: "json"
}
}
});
personSource2.fetch(function(){
var data = personSource2.data();
console.log(data.length); // displays "1"
console.log(data[0].name); // displays "a name string"
var personViewModel2 = kendo.observable({
dataSource: personSource2
});
var json = personViewModel2.toJSON();
console.log(JSON.stringify(json));
observName1 = personViewModel2.get("dataSource.data.name");
console.log("read observable: "+observName1);
kendo.bind($(''#repName''), personViewModel2);
});
After a lot of playing around, I managed to get the value to bind using:
data-bind="text: dataSource.data()[0].name"
but I can't find this documented anywhere.
Where I output the observable to the console, I get a great big object, not the simple observable data structure I was expecting. I suspect I am missing something fundamental here!
I am currently just trying to read the observable above, but can't get it to return the string from the json source.
personSource2.fetch(function(){
var data = personSource2.data();
console.log(data.length); // displays "1"
console.log(data[0].name); // displays "Jane Doe"
var personViewModel2 = kendo.observable({
dataSource: personSource2
});
var json = personViewModel2.toJSON();
console.log(JSON.stringify(json));
observName1 = personViewModel2.get("dataSource.data()[0].name");
console.log("read observable: "+observName1);
personViewModel2.set("dataSource.data()[0].name","Another Value");
observName1 = personViewModel2.get("dataSource.data()[0].name");
console.log("read observable: "+observName1);
kendo.bind($(''#repName''), personViewModel2);
});

Kendo UI: How to get the text input from the Multiselect

I'm trying to use Kendo UI MultiSelect to select some stuff from an API. The API won't return all items because they are too much. It will only return those that contains the searchTerm.
I'm trying to figure out how to send the input text in a Kendo UI Multiselect. When I say the input text, I mean what the user typed in the input before selecting anything from the list. That text has to be passed on to the DataSource transport.read option.
See this Codepen to understand
https://codepen.io/emzero/pen/NYPQWx?editors=1011
Note: The example above won't do any filtering. But if you type "bre", the console should log searching bre.
Use the data property in the read transport options, this allows you to modify the query being sent by returning an object that will later on be serialized in the request.
by default read are GET requests so it will be added to the queryString of your url specified.
If it were to be a POST it would be added to the POST values.
<div id="multiselect"></div>
<script>
$('#multiselect').kendoMultiSelect({
dataTextField: 'first_name',
dataValueField: 'id',
filter: "startswith",
dataSource: {
serverFiltering: true, // <-- this is important to enable server filtering
schema: {
data: 'data'
},
transport: {
read: {
url: 'https://reqres.in/api/users',
// this callback allows you to add to the request.
data: function(e) {
// get your widget.
let widget = $('#multiselect').data('kendoMultiSelect');
// get the text input
let text = widget.input.val();
// what you return here will be in the query string
return {
text: text
};
}
}
}
}
});
</script>

ExtJS: 2 ajax store, 1 with an extra row

I have this code:
Ext.define('storeBusiness',{
extend: 'Ext.data.Store',
autoLoad: true,
autoSync: true,
model: 'Business',
proxy: {
type: 'ajax',
api: {
read: '../crud/ler_filter.php?db='+database+'&tbl=mercados',
create: '../crud/criar.php?db='+database+'&tbl=mercados',
update: '../crud/update.php?db='+database+'&tbl=mercados',
destroy: '../crud/apagar.php?db='+database+'&tbl=mercados'
},
reader: {
type: 'json',
root: 'rows'
},
writer: {
type:'json'
}
}
});
var storeBusinessCombo = Ext.create('storeBusiness');
var storeBusiness = Ext.create('storeBusiness');
storeBusiness.add({id: 0, business: "All"});
I have 2 grids. One has storeBusiness and the other has storeProducts.
The way the work is when I click on the business grid it filters the produts grid so that it shows the products of that business.
On the business grid it has the storeBusiness that it fetches the records from a database. I want to fetch all business from the database and add one more record (named 'All') without writing it to the database.
I dont want to add 'All' to the database because in the Product's grid I want to have a combobox that has all the business (storeBusinessCombo) without the 'All' record.
Does anyone has any idea how I can do this?
(the code above isn't doing what I want, storeBusiness shows all business without the 'All' in the grid)
Important: This works if the Ext.define('storeBusiness', has a proxy that is of type: 'memory'
Two approaches come to mind:
Add the "all" record to the store after load and don't sync so the
record isn't sent to the server.
Use memory proxy, retrieve the
businesses records via Ajax request and assign them to the store via its data config.
To resolve this I have done:
Put the Ext.define('storeBusiness',{ to autoLoad: false,
Put this code:
var storeBusinessCombo = Ext.create('storeBusiness', {autoLoad: true});
var storeBusiness = Ext.create('storeBusiness');
storeBusiness.on('beforeload', function(){
storeBusiness.loadData([{id: 0, business: "All"}]);
}
And you should put
storeBusiness.load({addRecords: true});
when you want to load storeBusiness.

Kendo MVVM JayData(asKendoDataSource) inverseProperty with webSQL provider

I am attempting to develop a Mobile app using Kendo Mobile's MVVM and JayData Data Access Library. I have run into an issue that I have worked on for about a week now with no luck. I am looking for a simple example consisting of Kendo two way binding using a model that is created by JayData's (asKendoDataSource) having an inverseProperty navigation property. I am not sure that JayData kendo.js Module supports models containing inverseProperty and in the process of testing, even after getting the data to save with the relationship, retrieval of the same record does not pull the relational data back into the viewmodel.
Can anyone provided a simple example of Saving and Retrieving such a model using the webSql provider?
Any help is greatly appreciated.
JayData Models (simplified):
//Expense Category Model
$data.Entity.extend('data.types.ExpenseCategory', {
Id: { type: 'Edm.Guid', key: true },
CategoryName: { type: 'string', required: true, minLength: 3, maxLength: 26 },
Expenses: { type: Array, elementType: "data.types.Expense", inverseProperty: "Category" }
});
//Expense Model
$data.Entity.extend('data.types.Expense', {
Id: { type: 'Edm.Guid', key: true },
ExpenseDescription: { type: 'string', required: true },
Category: { type: "data.types.ExpenseCategory", inverseProperty: "Expenses" }
});
// Entity Context
$data.EntityContext.extend('data.types.DbContext',
{
ExpenseCategories: { type: $data.EntitySet, elementType: data.types.ExpenseCategory },
Expenses: { type: $data.EntitySet, elementType: data.types.Expense },
});
// Database Context
data.context = new data.types.DbContext({ name: 'sqLite', databaseName: 'cDb' });
Kendo Viewmodel (simplified):
views.expenseCategoryPicker = kendo.observable({
app: null,
categories: db.context.ExpenseCategories.asKendoDataSource(),
expense: null,
itemClick: function(sender) {
var expense = views.expenseCategoryPicker.expense;
expense.set('Category', sender.data);
...add/update logic
expense.sync();
},
loadExpense: function(dataItem) {
views.expenseCategoryPicker.set('expense', undefined);
views.expenseCategoryPicker.set('expense', dataItem);
},
});
EDIT
I figured out why the data won't save and a work around. There is a bug in JayData's kendo.js module when using the Kendo MMVM binding and inverseProperty relationships. They(JayData) simply don't support their own Attach method when an object relationship is being set through their Kendo module. Therefor when you call Kendo's SET on the model passing in the related Object the Entity state on the Object being passed in is set to 20 (New) and JayData tries to create a new record and in my case failing due to primary key conflict. The Attach method sets the Entity state to unmodified.
I know there is probably a more elegant way to fix this in JayData's code, but for me simply adding the following line right before I use the Kendo set method to set the object relationship allows the record to be saved without error.
itemClick: function(sender) {
var expense = views.expenseCategoryPicker.expense;
//manually set the state so SQL won't try to create a new record
sender.data.innerInstance()._entityState = 10;
expense.set('Category', sender.data);
...
Subsequent reads require the Include('model') method to load the relational data as mentioned by Robesz (THANK YOU)
It would be nice to see JayData fix the data save issue in their Kendo module.
JayData doesn't load the related entities by default, you have to use the include() operator:
data.context.Expenses.include('Category').toArray(...)
The parameter of the include should be the name of the navigation property.

jqgrid 4.5.4 jsonReader not using id correctly

I am defining the id field in the jsonReader. In jqgrid Version 4.4.5, this works great, but in Version 4.5.4, the id is ignored and the row numbers are always used. I have created two jsfiddles to demonstrate:
Double click on the row to get the id for that row.
This one correctly displays the id based on what's set in the jsonReader
(Scroll to bottom to see example grid code. I couldn't find external link to 4.4.5)
Version 4.4.5: http://jsfiddle.net/cVk59/1/
This one incorrectly displays the rowNumber for the id. It ignores what's set in jsonReader.
Version 4.5.4: http://jsfiddle.net/cnsgH/
jsonReader:{ repeatitems:false, id:'0'}
You use wrong value for jsonReader.id. Your current data, returned from the server, have the following format
...
rows: [
{id: 48803, thingy: "what"}
]
...
So the data for a row will be represented by an object like
var obj = {id: 48803, thingy: "what"};
To get id from the object one need to use jsonReader: { repeatitems: false, id: 'id' }. Because id: 'id' is already default value, you can use just jsonReader: { repeatitems: false }.
I try to explain the reason why id: '0' is wrong property of jsonReader in your case. jqGrid just use obj[jsonReader.id] to get the id for every row of data. So if you use jsonReader:{ repeatitems:false, id:'0'} then jqGrid trying to use obj['0'] which is wrong (undefined value). If you use jsonReader: { repeatitems: false, id: 'id'} instead (or just jsonReader: { repeatitems: false}) then obj[jsonReader.id] will be equal to obj['id'] or obj.id and the id will be successful read.
The property like jsonReader: { id: '0' } will be used if the data, represented a row, is array like
var obj = [48803, "what"];
In the case obj[jsonReader.id] will be equal obj['0'] or obj[0].

Resources