On my Kendo grid, I have "editable=true" and datasource with "autoSync=true". As I click on a cell, it becomes editable and when leaving the cell it executes the transport's update event.
That's all fine.
In the update event I have access to the row of the dataset model containing all the values of the modified row (although with editable=true and autosync, only one column value would have been modified).
I need to know which column / field was modified?
Ideally I thought that info would be in the arguments (options) supplied to the update event.
dataSource = new kendo.data.DataSource({
autoSync: true,
transport: {
update: function (options) {
// options does not tell me which model field was updated?
...
But since it isn't there, I suppose I need to bind to the model's set event, but I cannot get that to work.
Any ideas?
Never mind this answer! I read the question all wrong.
I think I got it working the way you like.
Is this jsFiddle what you're looking for?
var ds = new kendo.data.DataSource({
autoSync: true,
transport: {
read: function(options) {
options.success([
{ Id: 1, A: 'Hello', B: 'World' },
{ Id: 2, A: '1', B: '2' },
{ Id: 3, A: 'fdasf', B: '4523' }
]);
},
update: function (options) {
var uid = ds.data().find(function(p) {return p.Id == options.data.Id;}).uid;
var tr = $('#grid .k-grid-content tr[data-uid="'+uid+'"]');
console.log(tr);
//Do something with tr
}
},
schema: {
model: { id: "Id" }
}
});
$('#grid').kendoGrid({
dataSource: ds,
editable: true,
});
Related
I have the following code and I am trying to get the count of returned records without having to issue a second fetch() command:
dsOffers = new kendo.data.DataSource({
transport: {
read: {
url: PRODUCTAPI,
data: getOfferData()
}
},
serverPaging: true,
pageSize: 50,
schema: {
data: "results",
total: "count",
model: { id: "id" }
}
})
.bind("error", namespace.dataSource_error);
dsOffers.total(); // returns 0
// if I use this, my API is hit twice
dsOffers.fetch(function() {
console.log(dsOffers.total()); // returns 3
});
The problem is that it takes time loading the data (it happens asynchronously -in background/parallel-). If you print it just after the initialization you actually don't have the data available.
This is the correct behaviour.
If you don't want to do the second fetch you should print it in the dataBound event.
Hi is there any way to pass detailRow reference to a function using kendo grid template column?
Here is my trail.
function detailInit(e) {
detailRow = e.detailRow;
detailRow.find("#mygrid").kendoGrid({
dataSource: {
data: empModel,
},
columns: [
{
field: "empId",
title: "Emp ID",
template: '<a href="\\#" onclick="showEmpDetails(\'#= detailRow #\')"> }
]
});
});
Try to place every detailRow you retrieve at the detailInit into globally located array, then pass this index to your click method (or some sort of key - could be dictionary, rows has uid) and then make the method to read the row details from your array/collection based on the id you have passed in. (Ideally read the row details directly from your datasource by the uid, no need to duplicate the data.) Please refer to below code as pseudo code, I didn't have a chance to run it.
var rows = new Array();
$('.clickable').click(function () {
// get the id for your detail
var detailId = this.attr('detailId');
// pass it further
showEmpDetails(detailId);
});
function detailInit(e) {
detailRow = e.detailRow;
// add roe to your (cache) collection
rows[rows.legth] = detailRow ;
detailRow.find("#mygrid").kendoGrid({
dataSource: {data: empModel},
columns: [
{
field: "empId",
title: "Emp ID",
// add attribute onto your a tag
template: '<a href="\\#" detailId = "#= rows.legth #" class="clickable">'
}
]
});
});
function showEmpDetails(id) {
// read from your collection and do what you need
console.log(rows[id]);
}
i have developed a web application using kendo ui tools and theres a kendo grid with batch edit mode..
but when i press the delete button for any record in kendo grid it will erase from the list in grid but actually not in the data source.when i reload the page or grid the deleted item will still exist..
here is the code of my grid
<div id="grid">
</div>
<script type="text/javascript">
$("#submitMarketUser").click(function () {
var grid = $("#grid").data("kendoGrid");
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "WholeSaleTrade/GetTradeProductDetail",
dataType: "json",
data: {
test: $("#Names").val()
}
},
destroy: {
url: "WholeSaleTrade/DeletePro",
type: "POST",
dataType: "jsonp",
data: {
DAKy: $("#Names").val(),
DIKy: $("#btntxt").val()
}
},
create: {
url: "WholeSaleTrade/CreateProduct",
type: "POST",
dataType: "jsonp",
data: {
AKy: $("#Names").val(),
IKy: $("#btntxt").val()
}
}
},
pageSize: 5,
schema: {
model: {
id: "ProductKey",
fields: {
ProductKey: { editable: false, nullable: true },
ProductName: { validation: { required: true} }
}
}
}
});
$("#grid").kendoGrid({
dataSource: dataSource,
editable: true,
toolbar: ["create", "save"],
autobind: true,
pageable: true,
columns: [
{ field: "ProductName", title: "Product Name",
editor: function (container, options) {
var model = options.model;
$('<input id="btntxt" name="' + options.field + '"/>').appendTo(container).kendoComboBox({
dataSource: {
type: "POST",
transport: {
read: {
url: "MarketInformation/PopulateProducts",
success: function (data) {
var prod = data[0];
model.set("ProductName", prod.ItmNm);
model.set("ItmKy", prod.ItmKy);
model.set("UserKey", $("#Names").val());
}
}
}
},
dataValueField: "ItmKy",
dataTextField: "ItmNm"
});
}
},
{ command: ["destroy"], title: " " }
]
});
});
</script>
can not identify that where is the fault going and can somebody please help me to solve this matter.
There are three common reasons delete won't work:
1. Not setting editable of grid to inline or popup. The deleted items will be automatically processed through transport destroy only for "inline"/"popup" edit modes. Ex:
editable: {
mode: "inline",
}
//or
editable: "inline"
2. If on your datasource, you have the batch flag set to true, this means the datasource will make the call only after you tell it to, e.g calling sync(). Ex:
var dataSource = new kendo.data.DataSource({
batch: true,
//.....
});
//... in some where e.g in a save button click event call the following line:
dataSource.sync();
3. You should define id to your primary key of database field name inside model of datasource. Ex:
model: {
id: "ProductID",
fields: {
ProductID: { editable: false, nullable: true },
}
}
So the problem with your code is first one, i.e you did not set editable to inline or popup
If you choose not to include editable.mode in order to utilize the in-cell editing, you can set the toolbar of the grid to include the option save:
$("#grid").kendoGrid({
dataSource: {
transport: {
....
},
schema: {
....
}
},
toolbar: ["create", "save", "cancel"],
columns: [
....
],
editable: true
});
This will create a save button at the toolbar of the grid. After deleting any records by clicking the destroy command button, click on the save button to have the grid to make an Ajax call to the server to delete the record.
If you would rather delete the record automatically without including the save button, you could add a change event handler to the datasource of the grid:
$("#grid").kendoGrid({
dataSource: {
transport: {
....
},
schema: {
....
},
change: function(e) {
if (e.action === "remove") {
this.sync();
}
}
},
columns: [
....
],
editable: true
});
This will automatically sync the changes you made to the grid with the server when there's a data change.
Hmm try not including type: "POST", and see if it now works since as far as I can see that bit isn't included on the demo's and I don't think I included it when I last did inline edits/deletes.
I had put an arbitray name for an int on the server Delete Method.
[HttpPost]
public ActionResult DeleteRandomTest(Int32 randomTestId)
{
...
}
The default modelbinder was probably looking for a property called Id (same as the primary key of my type according to the configuration of the model).
.Model(config => config.Id(p => p.Id))
In fact, I proved this by changing the signature to the following:
[HttpPost]
public ActionResult DeleteRandomTest(Int32 Id)
{
...
}
My break point was hit after that.
Ultimately, I used the full type as the parameter as shown in the Kendo examples because I didn't want to have poorly named parameter names (not camel case) in the action. Shown as follows:
[HttpPost]
public ActionResult DeleteRandomTest([DataSourceRequest]
DataSourceRequest request, RandomDrugTest randomDrugTest)
{
...
}
This seems to the be the reason it wasn't working.
I had the same issue. My issue was caused by having a data property in the kendo model. Example:
{id: 1, data: ""}
I have created a custom component, in that there is a textfield on its keyup event i need to filter the store but i m not getting any variable at event generation, but at the time of object creation i am getting the objects.
Below is the code-:
WildCardWindow = Ext.extend(Ext.Window, {
width : 300,
height : 265,
resizable:true,
closeAction:'hide',
title:'WildCard Selection Window',
autoScroll:true,
iconCls:'icon-wildcard',
bodyStyle:'background-color:#FFFFFF',
//#cfg{Array} data-The array of fields/items to show in the window
data: null,
store:null,
/**
* #property
* #type String
* The message displayed when mouse over on an uncommitted field
*/
uncommittMsg : '<b>Warning!</b> This field has been newly added in
the form designer. ' + 'It <i>can</i> be used now,
but you should be sure to save the uncommitted
changes ' + 'in the open form designer window.',
defaultIconCls : '',
initComponent : function(){
this.createStore(this.data);
this.items = this.createDataView();
WildCardWindow.superclass.initComponent.call(this);
},
createDataView: function(){
this.dataView = new Ext.DataView({
store: this.store,
autoWidth:true,
tpl: this.createTpl(),
autoHeight:true,
singleSelect : true,
overClass:'icon-view-over',
selectedClass:'icon-view-selected',
itemSelector:'.icon-dataview-item',
style:'cursor:pointer'
});
this.textField = new Ext.form.TextField({
fieldLabel: 'To',
tabTip:'Start typing to filter by field name',
name: 'f_to',
enableKeyEvents :true,
listeners: {
keyup: function () {
this.store.filter('name',this.textField.getValue(),true,false);
//Here I am not getting this.store and this.textField ???
}}
});
return [this.dataView,this.textField]
},
createStore: function(data){
this.store = new Ext.data.JsonStore({
data:data,
autoDestroy:true,
fields:[
{name: 'id'},
{name: 'name'},
{name: 'fieldclass'},
{name: 'type'},
{name: 'options'},
{name: 'isMultiMember',type:'boolean'},
{name: 'isUnCommitted',type:'boolean'}
]
});
return this.store;
},
listeners:{
close: function(){
this.store.filter('name','',true,false);
}
}
})
In the keyup of textfield i am not getting this.store and this.textfield ??
Any suggestions or where i am wrong.
Please reply soon
Because you lose your scope when that function is called.
You can do two things:
Use the bind function to copy the scope:
http://docs.sencha.com/extjs/4.2.0/#!/api/Ext.Function-method-bind
I think this also works and is a more elegant solution:
var me = this;
this.textField = new Ext.form.TextField({
fieldLabel: 'To',
tabTip:'Start typing to filter by field name',
name: 'f_to',
enableKeyEvents :true,
listeners: {
keyup: function () {
me.store.filter('name',this.getValue(),true,false);
}}
});
I have a problem with the Kendo AutoComplete widget.
I am trying it to query the datasource after the user has entered the first two characters of their search.
On the server (web api) I restrict the search using those two chars and all is well, i.e. a subset is returned and correctly shown and further filtered if I carry on typing in the search.
However, I then retype a new search entry which is no longer firing back to the datasource so I am stuck with the data that was retrieved from the first query.
How do I go about this properly?
Thanks
Here is my test code:
public class AlbumsController : ApiController
{
HttpRequest _request = HttpContext.Current.Request;
// GET api/albums
public IEnumerable<Album> GetForAutoComplete()
{
string sw = _request["sw"] == null ? "" : _request["sw"].ToString();
var query = (from a in Albums.MyAlbums
where a.Title.ToLower().StartsWith(sw)
orderby a.Title
select a).ToArray();
return query;
}
and my javascript on the client is like this:
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "/api/Albums/GetForAutoComplete",
data: {
sw: function () {
return $("#albumSearch").data("kendoAutoComplete").value();
}
}
}
}
});
$("#albumSearch").kendoAutoComplete({
dataSource: dataSource,
dataTextField: "Title",
minLength: 2,
placeholder: "type in here.."
});
Set serverFiltering to true. The default is false, so it will only grab data once and assume that it now has all the data, and subsequent filtering is done on the client.
To have it re-send to the server every time, add this:
var dataSource = new kendo.data.DataSource({
serverFiltering: true, // <-- add this line.
transport: {
...
}
});
The code for selecting an European country while typing using kendo autocomplete from database as below:
$("#countries").kendoAutoComplete({
dataTextField: "yourfield",
filter: "startswith", // or you can use filter: "contains",
minLength: 3, //what ever you want. In my case its 0.
placeholder: "Select country...",
dataSource: {
type: "get",
serverFiltering: true, //or can also make it false
transport: {
read: {
url: "/yourController/yourAction",
datatype: "json"
}
}
}
});
It works fine for me.