I have kendo grid server side pagination and filtering based on start date and end date (2 Filters ), in first time grid drawn based on the 2 filters correctly .
When the 2 filters changed the grid draw correctly then when I go to another page the filters values sent to action server (action update data source) sent as firstly call not send current values .
Data source code is
dataSource: {
type: "aspnetmvc-ajax",
transport: {
read: {
url: "#Html.Raw(Url.Action("GetAllOldExcuse", "Security"))",
data: {
startDate: $('#FromDate').val(), endDate: $('#FromTo').val()
}
}
},
schema: {
model: {
fields: {
ID: { type: "number" },
}
}
, data: "Data",
total: "Total",
errors: "Errors",
AggregateResults: "AggregateResults",
},
pageSize: 10,
serverPaging: true,
serverSorting: true,
serverFiltering: true,
serverGrouping: true,
serverAggregates: true
}
Omar, you should change your data property into a function, so that it get re-evaluated each time the datasource requests data:
transport: {
read: {
url: "#Html.Raw(Url.Action("GetAllOldExcuse", "Security"))",
data: function() {
return {
startDate: $('#FromDate').val(),
endDate: $('#FromTo').val()
}
}
}
}
Related
I am trying to use js grid for my application. I am trying to populate the grid after ajax request but it do not seem to work as expected.
I am trying with SQL Server as back end and web application is asp.net MVC
This is my code in the html
var table;
var result;
var $j = jQuery.noConflict();
$j(document).ready(function () {
table = $j('#grid').jsGrid({
height: "60%",
width: "50%",
inserting: true,
editing: true,
sorting: true,
paging: true,
autoload: true,
pageSize: 10,
controller: {
loadData: function (filter) {
var d = $j.Deferred();
$j.ajax({
type: "POST",
contentType: "application/json",
url: "#Url.Action("LoadData", "User")",
datatype: "json",
data: filter
#*success: function (data) {
result = data.data;
console.log("result", result);
d.resolve(result)
},
error: function (data) {
window.location.href = '#Url.Action("Error", "Audit")';
}*#
}).done(function (data) {
console.log("response", data);
console.log("data.data", data.data);
d.resolve(data)
});
return d.promise();
},
fields: [
{ name: "LastName", type: "text"},
{ name: "FirstName", type: "text"},
{ name: "Email", type: "email"},
{ name: "PhoneNumber", type: "number"},
{ type: "control" }
]
}
});
});
In Controller I return
''return Json(new { data }, JsonRequestBehavior.AllowGet);''
I expect the json data to bind in the div. But it did not ? Thanks
Ok, so I've had this problem recently.
First off, change your "height" to px, auto, or get rid of it entirely. It's not doing what you think it's doing.
Next, since you have paging, you need to return your data in the following format:
{
data: [{your list here}],
itemsCount: {int}
}
It's barely in the documentation, as it's inline and not very obvious. (Bolding mine.)
loadData is a function returning an array of data or jQuery promise that will be resolved with an array of data (when pageLoading is true instead of object the structure { data: [items], itemsCount: [total items count] } should be returned). Accepts filter parameter including current filter options and paging parameters when
http://js-grid.com/docs/#controller
I use https://github.com/backbone-paginator/backbone.paginator to display data at a table whose columns are sortable. But when clicking on any header of a column, the sorting is done at the client instead of doing a new server request that should contain the attribute (e.g. name) that should be used to sort the results.
Base class
module.exports = Backbone.PageableCollection.extend({
initialize: function (items, options) {
options || (options = {});
this.url = options.url || "/";
},
state: {
pageSize: 15,
firstPage: 0,
currentPage: 0
},
queryParams: {
sortKey: 'sort',
pageSize: 'size',
currentPage: 'page'
},
parseState: function (resp) {
return {totalRecords: resp && resp.length > 0 ? resp[0]['total_entries'] : 0};
},
parseRecords: function (resp) {
return resp && resp.length > 0 ? resp[1] : [];
},
model: Backbone.NestedModel
});
Example Instantiation
collections.myTasks = new collections.PagingCollection([], {
model: models.SyncModel.extend({
url: URLs.TASKS
}),
url: URLs.MY_TASKS,
state: {
pageSize: 30,
firstPage: 0,
currentPage: 0,
}
});
Columns
columns: [
{
name: "dueDate",
label: "Due Date",
cell: "date",
filterCell: FilterCell,
editable: false,
width: "80px"
},
{
name: "reminder",
label: "Reminder",
filterCell: FilterCell,
cell: Backgrid.StringCell.extend({
formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
fromRaw: function (rawValue, model) {
return DateHelper.format(
IntervalHelper.calculateBefore(model.attributes['dueDate'], rawValue)
);
}
})
}),
editable: false,
width: "80px"
},
{
name: "name",
label: "Subject",
cell: "string",
filterCell: FilterCell,
editable: false,
width: "auto"
},
{
name: "taskStatusCtlg.taskStatus",
label: "State",
filterCell: SelectFilterCell.extend({
filterField: 'taskStatus',
addAllOption: true
}),
cell: "string",
width: "75px"
},
{
name: "assignedTo.alfrescoUserName",
label: "Assigned To",
cell: "string",
filterCell: SelectFilterCell.extend({
filterField: 'assignee',
addAllOption: true
}),
editable: false,
width: "120px"
},
{
name: "taskTypeCtlg.taskType",
label: "Type",
cell: "string",
filterCell: SelectFilterCell.extend({
filterField: 'taskType',
addAllOption: true
}),
editable: false,
width: "70px"
},
{
name: "mainDocument.name",
label: "Case / Document",
link: "mainDocument.id",
cell: LinkCell,
filterCell: FilterCell,
editable: false,
width: '160px'
}
],
Fetching the data etc. is done without problems. But when clicking on a caret sorting is done on the client. But I need that attributes "sort" and "order" get append to the request URL when clicking on a column header (sorting on the server).
Current request:
http://localhost/tasks/user?page=0&size=30
Needed request:
http://localhost/tasks/user?page=0&size=30&sort=name&order=asc
Paginator offers 3 modes for the fetching and sorting:
client: all on the client. Feed the data yourself.
server: Fetch the data from an API (e.g.: collection.getFirstPage()) and receive the total number of pages.
infinite: like the server mode, but best used with unknown number of pages. Like a search result from an external API.
Ensure that you're using the server value for the mode property on the PageableCollection.
var books = new Books([
{ name: "A Tale of Two Cities" },
{ name: "Lord of the Rings" },
// ...
], {
// Paginate and sort on the server side, this is the default.
mode: "server",
});
or within your collection class definition:
module.exports = Backbone.PageableCollection.extend({
mode: "server", // this is the default
initialize: /*...*/
Other than that, this is likely solvable within Backgrid.
The default of Backgrid is to sort on the client. For a custom behavior, you can
provide a Backbone.PageableCollection
or override the HeaderCell view with your own implementation
Using a Backbone.PageableCollection
Set the collection property of the Grid.
var taskGrid = new Backgrid.Grid({
collection: collections.myTasks,
columns: [/*...*/],
});
Overriding the HeaderCell view
You are allow to use a different header cell class on columns. There is no restriction on what a header cell must do. In fact, any Backbone.View class can be used. However, if you wish to modify how the sorter behaves, you must
implement the sorting protocol. See the JSDoc for details.
var SelectAllHeaderCell = Backgrid.HeaderCell.extend({
// Implement your "select all" logic here
});
var grid = new Backgrid.Grid({
columns: [{
name: "selected",
label: "",
sortable: false,
cell: "boolean",
headerCell: SelectAllHeaderCell
}],
collection: col
});
Note (2017/01/30): Links to the API documentation within the documentation are not up to date, this is being discussed in issue #664.
I am using ExtJs 4.2 and I have a Ext.grid.Panel and I have data coming in, but i want them to be ordered upon ingestion based on a boolean flag with things that have true for one field at the top, true for another field next, with false in both fields coming at the bottom. So far I have editing the sorters as prescribed below.
me.requesterListStore = new Ext.create('Ext.data.Store', {
id: 'requesterListStore',
model: 'Connex.Request.Model.RequesterModel',
buffered: true,
pageSize: 100,
leadingBufferZone: 50,
autoLoad: false,
remoteFilter: false,
purgePageCount: 5,
remoteSort: false,
sortOnLoad: true,
sorters: [
{
property: 'isSmartIndexed',
direction: 'DESC'
},
{
property: 'isAutoIndexed',
direction: 'DESC'
}
],
proxy: {
type: 'ajax',
url: $context + 'services/requester/search',
actionMethods: {
read: 'POST'
},
doRequest: function (operation, callback, scope) {
var writer = this.getWriter(),
request = this.buildRequest(operation, callback, scope);
if (operation.allowWrite()) {
request = writer.write(request);
}
Ext.apply(request, {
headers: this.headers,
timeout: this.timeout,
scope: this,
callback: this.createRequestCallback(request, operation, callback, scope),
method: this.getMethod(request),
jsonData: this.jsonData,
disableCaching: false // explicitly set it to false, ServerProxy handles caching
});
Ext.Ajax.request(request);
return request;
},
reader: {
type: 'json',
root: 'content',
totalProperty: 'total',
idProperty: 'id'
},
writer: {
writer: new Ext.data.JsonWriter({
getRecordData: function (record) {
return record.data;
}
})
}
}
});
sorters: [{
property: 'isSmartIndexed',
direction: 'DESC' // or 'ASC'
}, {
property: 'isAutoIndexed',
direction: 'DESC' // or 'ASC'
}]
Add these sorters to your store.
True is always bigger than false ;)
Keep attenction, you can't use sortingFuntions on a bufferedStore like written here:
If the store is buffered, then prefetchData is stored by index, this invalidates all of the prefetchedData.
because in your case you will order only the displayed data on the grid, and not the others that will be loaded.
Test it in this fiddle.
I am starting to look at how I would get my grid edits back to a service via the datasource.
Following the documentation, I have set a local test data source as follows..
function getDataSource() {
var gridData = [
{
col1: new CellData('1', 'data1-1'),
col2: new CellData('2', 'data1-2')
},
{
col1: new CellData('3', 'data2-1'),
col2: new CellData('4', 'data2-2')
},
];
var dataSrc = new kendo.data.DataSource({
batch: true,
transport: {
read: function (e) {
e.success(gridData);
},
update: function (e) {
// batch is enabled
var updateItems = e.data.models;
// This is not called
// on success
e.success();
},
create: function (e) {
e.success(e.data);
},
destroy: function (e) {
e.success();
}
}
});
return dataSrc;
}
I have a toolbar setup (with the "Save Changes"), and this is calling the SaveChanges configuration event, how ever, just cannot see what else I need to do to get the following to occur..
Have the data sources update called
Mark the grid "on dirty" so that the red "edited" indicators on the edited cells disappear
I am having the same problem with the Add New record (though I can't get the grids "addRow" even to fire here)
I have the running example here
Any help would be great appreciated!
You need to specify the DataSource schema for this to work:
var dataSrc = new kendo.data.DataSource({
batch: false, // true would mean transport functions get multipe models in e.data
transport: {
// ....
},
schema: {
data: function (response) {
return response;
},
model: {
id: "id",
fields: {
id: {
editable: false,
defaultValue: 0 // 0 == new / unsaved row
},
col1: {
editable: true,
// new items would have that using default add button
defaultValue: {
id: 0,
CategoryName: ""
},
fields: { id: { editable: true }, display: { editable: true }
},
col2: {
editable: true,
fields: { id: { editable: true }, display: { editable: true } }
}
}
}
}
});
Also note:
grid.saveChanges will sync the DS, so you don't need to do anything in the event
There is no addRow event.
The default "create" button will try to add an empty object; since you work with nested objects, you need to add the row yourself so you can initialize the properties; thus you need a custom button and bind your action manually
(demo)
Been trying to do an update on a Kendo grid and I'm having issues.
I'm using Rails as the back-end and when I do the update, the server seems to be showing that everything worked:
Started PUT "/" for 127.0.0.1 at 2012-02-12 17:28:19 -0600
Processing by HomeController#index as
Parameters: {"models"=>"[{\"created_at\":\"2012-02-08T17:34:50Z\",
\"first_name\":\"Milla\",\"id\":2,\"last_name\":\"sfasfsdf\",\"password\":\"\",
\"updated_at\":\"2012-02-08T17:34:50Z\",\"user_name\"
:\"\"}]"}
Rendered home/index.html.erb within layouts/application (3.0ms)
Completed 200 OK in 89ms (Views: 88.0ms | ActiveRecord: 0.0ms)
However, when I refresh the view, nothing has changed. When I checked the database, of course no changes had taken place there either.
I went through the documentation here about how to do edits in the grid: http://demos.kendoui.com/web/grid/editing.html
And I watched Burke Hollands video about how to set up the grid to work with Rails: http://www.youtube.com/watch?v=FhHMOjN0Bjc&context=C3f358ceADOEgsToPDskKlwC22A9IkOjYnQhYyY9HI
There must be something that I haven't done right, but I'm just not seeing it.
Here's my code that works with the Kendo stuff:
var User = kendo.data.Model.define({
id: "id",
fields: {
first_name: { validation: { required: true } },
last_name: { validation: { required: true } }
}
});
var UsersData = new kendo.data.DataSource({
transport: {
read: {
url: "/users.json"
},
create: {
url: "/users/create.json",
type: "POST"
},
update: {
type: "PUT"
},
destroy: {
type: "DELETE"
},
parameterMap: function(options, operation) {
if (operation !== "read" && options.models) {
return {models: kendo.stringify(options.models)};
}
}
},
batch: true,
pageSize: 5,
schema: {
model: User
}
});
$("#users-grid").kendoGrid({
dataSource: UsersData,
navigatable: true,
editable: true,
selectable: true,
pageable: true,
sortable: true,
toolbar: ["create", "save", "cancel"],
columns: [
{
field: "first_name",
title: "First Name"
},
{
field: "last_name",
title: "Last Name"
},
]
});
Some more research and I've got it working like this...
I added a route to override the 7 RESTful routes that Rails gives you by default. In your Routes.rb files, add this line...
match 'users' => 'users#update', :via => :put
Which basically says we are going to handle all puts by going to the update definition on the controller.
Now in the controller definition, you want to handle the update a bit differently since it's not RESTful. You need to first parse the JSON that you are sending via the parameterMap and then iterate through the objects updating with the object attributes...
def update
respond_to do |format|
#users = JSON.parse(params[:models])
#users.each do |u|
user = User.find(u["id"])
unless user.nil?
user.update_attributes u
end
end
format.json { head :no_content }
end
end
You can also modify your datasource because the url key can take a function:
var UsersData = new kendo.data.DataSource({
transport: {
read: {
url: '/users.json',
dataType: 'json'
},
update: {
url: function (o) {
return '/users/' + o.id + '.json'
},
dataType: 'json',
type: 'PUT'
},
destroy: {
url: function (o) {
return '/users/' + o.id + '.json'
},
dataType: 'json',
type: 'DELETE',
},
create: {
url: '/users.json',
dataType: 'json',
type: 'POST'
},
parameterMap: function(options, operation) {
if (operation !== "read" && options.models) {
return {models: kendo.stringify(options.models)};
}
}
},
batch: true,
pageSize: 5,
schema: {
model: User
}
});