kendogrid batch edit appending row causes to post data - datagrid

This code populates datagrid with json formated data received from /api/notes/ by tornado app...
$(document).ready(function () {
dataSource = new kendo.data.DataSource({
pageSize: 10,
autoSync: true,
transport: {
read: {
url: '/api/notes/',
dataType: 'json',
type: 'GET'
},
create: {
url: '/api/notes/',
dataType: 'json',
type: 'POST'
},
update: {
url: '/api/notes/',
dataType: 'json',
type: 'PUT'
}
},
schema: {
data: function(reply) { return reply.rows; },
model: {
id: "id",
fields: {
id: { type: "string" },
name: { type: "string" },
author: { type: "string" },
}
}
},
});
$("#grid").kendoGrid({
dataSource: dataSource,
navigatable: true,
pageable: true,
height: 300,
editable: true,
toolbar: ["create", "save", "cancel"],
columns: [
{ field: "id", title: "ID", width: 150 },
{ field: "name", title: "Book", width: 150 },
{ field: "author", title: "Author", width: 100 },
{ command: "destroy", title: " ", width: 110 }
],
});
});
if I click create instead of popping up a row, like here a post triggered with empty data parameter, what's wrong here

Try it with autoSync removed or set to false on the DataSource. According to the docs:
Enables (true) or disables (false) the automatic invocation of the sync() method for each change made.
So I think when you try to insert the row, it immediately puts it into the DataSource, causing it to do a sync(). The demo you linked to doesn't specify autoSync either.

Related

ASP.NET WebAPI KendoUI, can't update, create, delete data, 405 Method not allowed

I'm using ASP.NET WebApi in conjunction with KendoUI. Json is successfully displayed in the grid, so GET works. But I can't UPDATE, CREATE or DELETE data. Any idea what I am missing? Even in the Telerik forum I couldn't find anything that points me into the right direction. And I also looked through their examples. Must I somehow pass values to PUT, POST, and DELETE?
<script type="text/javascript">
var remoteDataSource = new kendo.data.DataSource({
transport: {
read: { url: '/api/NorthwindProductWebApi', dataType: "json", type: "GET" },
update: { url: '/api/NorthwindProductWebApi', dataType: "json", type: "PUT"},
create: { url: '/api/NorthwindProductWebApi', dataType: "json", type: "POST" },
destroy: { url: '/api/NorthwindProductWebApi', dataType: "json", type: "DELETE" },
parameterMap: function (options, operation) {
if (operation !== "read" && options.models) {
return { models: kendo.stringify(options.models) }
;
}
}
},
pageSize: 20,
batch: true,
schema: {
model: {
id: "ProductID",
fields: {
ProductID: { type: "number" },
ProductName: { type: "string" },
SupplierID: { type: "number" },
CategoryID: { type: "number" },
QuantityPerUnit: { type: "string" },
UnitPrice: { type: "string" },
UnitsInStock: { type: "number" },
UnitsOnOrder: { type: "number" },
ReorderLevel: { type: "number" },
Discontinued: { type: "string" }
}
}
}
});
$('#grid').kendoGrid({
dataSource: remoteDataSource,
heigth: 100,
groupable: true,
sortable: true,
pageable: {
refresh: true,
pageSizes: true,
buttonCount: 5
},
toolbar: ["create"],
columns: [{
command: ["edit", "destroy"], title: " ", width: "200px"
},
{
field: "ProductID",
title: "ProductID",
width: 200
}, {
field: "ProductName",
title: "ProductName",
width: 250
}, {
field: "SupplierID",
title: "SupplierID",
width: 200
}, {
field: "CategoryID",
title: "CategoryID",
width: 200
}, {
field: "QuantityPerUnit",
title: "QuantityPerUnit",
width: 200
}, {
field: "UnitPrice",
title: "UnitPrice",
width: 250
}, {
field: "UnitsInStock",
title: "UnitsInStock",
width: 200
}, {
field: "UnitsOnOrder",
title: "UnitsOnOrder",
width: 250
}, {
field: "ReorderLevel",
title: "ReorderLevel",
width: 200
}, {
field: "Discontinued",
title: "Discontinued",
width: 250
}],
editable: "popup",
save: function(){
this.refresh();
},
scrollable: true,
filterable: {
extra: false,
operators: {
string: {
startswith: "beginnt mit",
eq: "exakt",
neq: "enthält nicht"
},
number: {
//???contains: "contains",
eq: "exakt",
//???doesnotcontain: "Is not equal to"
}
},
}
});
</script>
Update:
Chrome gives me a 405 Method not allowed method on PUT and a 500 (Internal Server Error) on POST. Here is a snippet from the scaffold WebApi Controller and the chrome output, which is the same for both errors:
POST http://localhost:123/api/NorthwindProductWebApi 500 (Internal Server Error) jquery-1.10.2.js:8720
send jquery-1.10.2.js:8720
jQuery.extend.ajax jquery-1.10.2.js:8150
ct.extend.create kendo.all.min.js:11
(anonymous function) kendo.all.min.js:11
jQuery.extend.Deferred jquery-1.10.2.js:3274
lt.extend._promise kendo.all.min.js:11
lt.extend._send kendo.all.min.js:11
lt.extend.sync kendo.all.min.js:11
j.extend.saveRow kendo.all.min.js:23
(anonymous function) kendo.all.min.js:22
jQuery.event.dispatch jquery-1.10.2.js:5109
elemData.handle jquery-1.10.2.js:4780
// POST api/NorthwindProductWebApi
[ResponseType(typeof(Product))]
public IHttpActionResult PostProduct(Product product)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Products.Add(product);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = product.ProductID }, product);
}
Attempt to change the Url in the DataSource:
create: {
url: function(options) {
return '/api/NorthwindProductWebApi/PostProduct' + options.ProductID
},
type: "POST",
dataType: "json"
Normally you decorate your controller with
[HttpGet]
[HttpPost]
If you decided to use full set of REST request methods ,Get,Put,Delete,Post then you must handle them by decorating on the controller method to tell the compiler which method will be processing which type of request.
[HttpGet]
public ActionResult HelloWorld()
{}
[HttpPost]
public ActionResult HelloWorld(Model model)
{}
[HttpPut]
public ActionResult HelloWorld(Model model)
{}
[HttpDelete]
public ActionResult HelloWorld(int Id)
{}
For more information Link: PUT vs POST in REST
Ok, so, your controller is named NorthwindProductWebApiController and your POST method in the controller is named PostProduct. The solution is one of two choices. You can either rename PostProduct to Post - removing the Product part in the name, or change the url in your Kendo DataSource create definition to api/NorthwindProductWebApi/PostProduct.
Remember that ASP.NET WebApi is based on convention. You do not have to fully name your controller methods. Typically, the HTTP verb is sufficient. It knows which method to call based on the verb and number of arguments. If you do however fully name the method, you must fully name it in the URL.

How to perform custom paging in Ext Grid

I have following Ext Grid,
Ext.onReady(function () {
var dataStore = new Ext.data.JsonStore({
proxy: {
type: 'ajax',
url: 'Default.aspx/CustomerData', //'web.aspx',
headers: { 'Content-type': 'application/json' },
reader: {
type: 'json',
root: 'd',
totalProperty: 'totalCount'
}
},
fields: [
{ name: 'firstname', type: 'string' },
{ name: 'lastname', type: 'string' },
{ name: 'age', type: 'string' },
{ name: 'phone', type: 'string' }
],
pageSize: 10
});
dataStore.load({ params: { start: 0, limit: 25} });
var myGrid1 = new Ext.grid.GridPanel({
id: 'customerslist',
store: dataStore,
columns: [
{ id: "firstname", header: "First Name", width: 100, dataIndex: "firstname", sortable: true },
{ header: "Last Name", width: 100, dataIndex: "lastname", sortable: true },
{ header: "Age", width: 100, dataIndex: "age", sortable: true },
{ header: "Phone", width: 100, dataIndex: "phone", sortable: true }
],
autoLoad: false,
stripeRows: true,
autoHeight: true,
width: 450,
height: 300,
dockedItems: [{
xtype: 'pagingtoolbar',
store: dataStore,
dock: 'bottom',
displayInfo: true
}],
renderTo: 'grid1'
});
});
I have following server side code for custom paging,
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true, XmlSerializeString = false)]
public static List<tblCustomerList> CustomerData(int rowSize, int pageNumber)
{
DataGridEntities _dbContext = new DataGridEntities();
//Code for custom paging
Customer customer = new Customer();
customer.TotalRecords = //code for total record count
customer.Details = //fetch record based on page number and page size
return customer.Details;
}
}
How can I achieve custom Paging in this.
Paging is done with start and limit per default. And if you don't want to rewrite the whole chain I recommend you to leave it as it is an simply add two more params, in your case
dataStore.load({
params: {
rowSize: dataStore.pageSize,
pagenNumber: dataStore.currentPage || 1
}
});
In addition you will need either a custom paging navigation, a customized version of the paging toolbar or a beforeload eventhandler like this:
function(store,operation,eo){
operation.params: {
rowSize: store.pageSize,
pagenNumber: store.currentPage +1 // I assume that this was not updated before a successful load
}
}
This is untested and should show you how it can be done.

After edit of Grid cell, the value is overlapped with a zero

When I edit a cell in my grid, a zero ("0") is placed in the cell, overlapping the cell value. This zero does not show when the grid loads, and it does not save to the database when the update happens. If I navigate away and come back, the zero is gone. It only happens if I edit the cell; if I only click in the cell and initiate the inline editing, no zero appears. This happens in every cell, even the dates.
My page is an SPA.
This is the code that builds the grid:
function fnLoadStorageVaults(storageid) {
var ds = new kendo.data.DataSource({
transport: {
read: {
url: URL_GETVAULTS,
dataType: "json",
type: "GET",
data: { StorageID: storageid }
},
update: { dataType: "json", url: URL_UPDATEVAULTS, type: "POST" },
destroy: { url: URL_DELETEVAULT, type: "POST" },
create: { url: URL_INSERTVAULT, type: "POST" },
parameterMap: function (data, type) {
return kendo.stringify(data);
}
},
autoSync: true,
schema: {
model: {
id: "StorageVaultID",
fields: {
VaultNumber: { type: "string", editable: true },
Section: { type: "string", editable: true },
Row: { type: "string", editable: true },
DateFrom: { type: "date", editable: true },
DateTo: { type: "date", editable: true },
WarehouseID: { type: "number", editable: true }
}
}
}
});
$("#VaultGrid").kendoGrid({
dataSource: ds
, sortable: true
, editable: true
, navigable: true
, columns: [
{ field: "WarehouseID", title: "Warehouse", width: "60px" }
,{ field: "VaultNumber", title: "Vault Nbr.", width: "60px" }
, { field: "Section", title: "Section" }
, { field: "Row", title: "Row" }
, { field: "DateFrom", title: "Date In" }
, { field: "DateTo", title: "Date Out" }
]
});
}
My apologies, the update was not working after all. The zero was the response from the server. Still curious behavior though.

Kendo Grid PopUp Editor Will Not Close

I have a basic grid with
editable: "popup"
I have a command column with "edit" in it. I am using a remote data source with read, update, create and destroy defined. The grid works, and when I click Edit, the popup window appears with all my fields in it. If I enter some changes in the fields and click Update, the data gets submitted (I can see the ajax post) but the popup window does not close.
My Update button has these classes "k-button k-button-icontext k-grid-update".
My popup window has these classes "k-widget k-window".
The Cancel button closes the window and the X in upper right closes the window too.
Any ideas?
My datasource code:
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "myReadURL",
dataType: "json"
},
update: {
url: "myUpdateURL",
dataType: "json"
},
create: {
url: "myCreateURL",
dataType: "json"
},
destroy: {
url: "myDestroyURL",
dataType: "json"
}
},
schema: {
data: "data",
total: function(response){return $(response.data).length;},
model: {
id: "id",
fields: {
id: { type: "number", editable: false },
location: { type: "string" },
username: { type: "string" },
host: { type: "string" },
model: { type: "string" },
newhost: { type: "string" },
newserial: { type: "string" },
newassettag: { type: "string" },
complete: { type: "boolean" }
}
}
},
pageSize: 10
});
My Grid init code:
$("#grid").kendoGrid({
dataSource: dataSource,
height: 430,
filterable: true,
sortable: true,
resizable: true,
scrollable: true,
pageable: {
refresh: true,
pageSizes: [10,20,100]
},
columns: [{
hidden: true,
field:"id"
},{
command: "edit",
title: " ",
width: 90
},{
field: "location",
title: "Location",
width: 120,
filterable: {ui: cityFilter}
},{
field: "username",
title: "Username",
width: 120
},{
field: "host",
title: "Host",
width: 180
},{
field: "model",
title: "Model",
width: 180
},{
field: "newhost",
title: "New Host",
width: 180
},{
field: "newserial",
title: "New Serial",
width: 180
},{
field: "newassettag",
title: "New Asset",
width: 180
},{
field: "complete",
title: "Complete",
template: "<input type='checkbox' # if(complete){ # checked #} #/>",
width: 70
}
],
editable: "popup"
});
My html:
<div id="example" class="k-content">
<div id="grid" style="height: 380px"></div>
</div>
Your service needs to return a valid JSON document, even if it is empty. If your service does not respond anything or returns something not parseable as JSON, then it will not close the popup.
For example: Create a file called myUpdateURL that simply contains:
{}
and it should work.

ExtJS reloading store on button click event with different parameter

I am new to ExtJs and I am using ExtJs4.
Now As shown in below image, There is one textfield named keywords, What I want to do is When I click on the button it will pass data of textfield to servlet and display resulted record in grid.
Now I have no idea how to do this. I am receiving JSON data response from servlet but don't know how to reload the store and refresh the grid.
Below is code for my store and grid.
Ext.define("Post", {
extend: 'Ext.data.Model',
proxy: {
type: 'ajax',
url: '/ezdi/searchServlet',
method: 'POST',
reader: {
type: 'json',
root: 'rows'
//,totalProperty: 'totalCount'
}
},
fields: [{
name: 'docid',
mapping: 'docid'
}, {
name: 'mrn',
mapping: 'mrn'
}, {
name: 'fname',
mapping: 'fname'
}]
});
var gridDataStore = Ext.create('Ext.data.Store', {
model: 'Post'
});
// Data store for grid end
Ext.define('Ezdi.Grid', {
extend: 'Ext.grid.GridPanel',
alias: 'widget.ezdigrid',
initComponent: function() {
var config = {
store: gridDataStore,
columns: [{
header: "DocID",
width: 100,
sortable: true,
dataIndex: 'docid'
}, {
header: "MRN",
width: 100,
sortable: true,
dataIndex: 'mrn'
}, {
header: "FirstName",
width: 100,
sortable: true,
dataIndex: 'fname'
}],
viewConfig: {
forceFit: false,
autoLoad: false
},
loadMask: true
};
}
});
You could use:
{
xtype: 'button',
text: 'Search',
handler: function() {
store.clearFilter(); //clear previous search value
var searchValue = Ext.getCmp("textFieldId").getValue(); //get new value
store.load().filter('jsonGridFielName', searchValue); //load filtered data
}
}
And for for multiple textfield search:
//FILTERS
var searchValue1 = Ext.getCmp("textFieldId1").getValue(); //value1
var searchValue2 = Ext.getCmp("textFieldId2").getValue(); //value2
var noValue = "0000xxxx"; //no Value, for empty field, use value that you are sure it is not going to be searched!!!
var clear = store.clearFilter(); //shortcut
if (!searchValue1 && !searchValue2) {
clear;
store.load().filter("jsonGridFielName1", noValue);
} else if (searchValue1) {
clear;
store.load().filter('jsonGridFielName1', searchValue1);
//...else if(searchValue n...)...
} else {
clear;
store.load().filter('jsonGridFielName2', searchValue2);
}
ezdigrid.js
// Data store for grid start
Ext.define("Post", {
extend: 'Ext.data.Model',
proxy: {
type: 'ajax',
url: '/ezdi/searchServlet',
method: 'GET',
reader: {
type: 'json',
root: 'rows'
//,totalProperty: 'totalCount'
}
},
fields: [{
name: 'docid',
mapping: 'docid'
}, {
name: 'mrn',
mapping: 'mrn'
}, {
name: 'fname',
mapping: 'fname'
}]
});
var gridDataStore = Ext.create('Ext.data.Store', {
// pageSize: 10,
model: 'Post'
});
// Data store for grid end
Ext.define('Ezdi.Grid', {
extend: 'Ext.grid.GridPanel',
alias: 'widget.ezdigrid',
initComponent: function() {
var config = {
store: gridDataStore,
columns: [{
//id:'ms',
header: "DocID",
width: 100,
sortable: true,
dataIndex: 'docid'
}, {
header: "MRN",
width: 100,
sortable: true,
dataIndex: 'mrn'
}, {
header: "FirstName",
width: 100,
sortable: true,
dataIndex: 'fname'
}],
viewConfig: {
forceFit: false,
autoLoad: false
},
loadMask: true
}; // eo config object
// apply config
Ext.apply(this, Ext.apply(this.initialConfig, config));
// call parent
Ezdi.Grid.superclass.initComponent.apply(this, arguments);
// load the store at the latest possible moment
this.on({
afterlayout: {
scope: this,
single: true,
fn: function() {
this.store.load({
params: {
start: 0,
limit: 30
}
});
}
}
});
} // eo function initComponent
});
demo.html
//handler for button click event
fbar: [{
xtype: 'button',
text: 'Search',
handler: function() {
var value = Ext.getCmp('_keyword').getValue(); //_keyword is textField
gridDataStore.load().filter('keywords', value);
}
}]
MyServlet
keyword = request.getParameter("keywords");
//code for quesry processing
Use extraParams in your model.
extraParams: {
keywords: 'your-value'
}
Put following code in your button click handler.
gridDataStore.proxy.extraParams.keywords = 'new value';
gridDataStore.load();

Resources