I am using datatables with server side processing. It sends all parameters to the server for even a basic operation like column sorting. How to prevent it, any idea? Here is the ajax get parameters that are passed as query string.
columns[0][data] 0
columns[0][name]
columns[0][orderable] true
columns[0][search][regex] false
columns[0][search][value]
columns[0][searchable] true
columns[1][data] 1
columns[1][name]
columns[1][orderable] true
columns[1][search][regex] false
columns[1][search][value]
columns[1][searchable] true
columns[2][data] 2
columns[2][name]
columns[2][orderable] true
columns[2][search][regex] false
columns[2][search][value]
columns[2][searchable] true
draw 2
length 10
order[0][column] 1
order[0][dir] asc
search[regex] false
search[value]
start 0
Here is the datatable initialization javascript code,
$(selector).dataTable({
"processing": true,
"serverSide": true,
"ajax": url,
"autoWidth": false,
"aoColumnDefs":[
{
'aTargets': 0,
'bSortable': true
},
{
'aTargets': 1,
'bSortable': true,
'mRender': function (link) {
return '' + link + '';
}
},
{
'aTargets': 2,
'bSortable': true,
'mRender': function (link) {
return '' + link + '';
}
}
]
});
Like this?
$(selector).dataTable({
"processing": true,
"serverSide": true,
"ajax": url,
"autoWidth": false,
"aoColumnDefs":[{
'aTargets': 0,
'bSortable': true
}, {
'aTargets': 1,
'bSortable': true,
'mRender': function (link) {
return '' + link + '';
}
}, {
'aTargets': 2,
'bSortable': true,
'mRender': function (link) {
return '' + link + '';
}
}],
fnServerParams: function(query_strings) {
query_string.splice(0);
/*
query_strings is an Array of Objects like this
[{name: 'query_string1', value: 'query_string1_value'},
{name: 'query_string2', value: 'query_string2_value'},
{name: 'query_string3', value: 'query_string3_value'}]
As you can see, the 'name' and 'value' represents the query string's key/value pair.
If you want to add another one you need to add another object:
query_string.push({
name: 'page',
// To get the page number you are going to
value: $(selector).dataTable().api().page.info().page
});
*/
}
});
Related
How can i use a resolve in a param default value, something like
params: {
id: {
type: 'int',
value: ['lists', function(lists) {
return lists[0].id; <====
}],
squash: false,
dynamic: false
}
},
resolve: {
lists: ['MailingListService', function (MailingListService) {
//load the tree data
return MailingListService.getMailingLists().then(function (lists) {
return lists;
});
}],
},
Because parameters have to be processed synchrounously, you cannot use a resolve in a default parameter value.
However, you can use a placeholder value such as null and map it to a resolve value later.
params: {
id: {
type: 'int',
value: null,
squash: false,
dynamic: false
}
},
resolve: {
lists: ['MailingListService', function (MailingListService) {
//load the tree data
return MailingListService.getMailingLists().then(function (lists) {
return lists;
});
}],
listId: ['lists', '$stateParams', function($stateParams) {
return ($stateParams.id === null) lists[0].id : listId;
}],
list: ['MailingListService', 'listId', function (MailingListService, listId) {
return MailingListService.getMailingList(listId);
}],
},
Used Kendo Version: 2015.2.624
I have implemented kendogrid server side paging with additional parameters. Below is how my controller looks like:
public ActionResult GetData([DataSourceRequest] DataSourceRequest request, DateTime startDate, DateTime endDate, int state = -1, string poolName = null, string submitter = null)
{
poolName = string.IsNullOrEmpty(poolName) ? null : poolName;
submitter = string.IsNullOrEmpty(submitter) ? null : submitter;
var summarylist = new List<Summary>();
var total = 0;
using (var db = new SummaryEntities())
{
var jobs = db.SummaryTable.Where(k => k.created >= startDate && k.created <= endDate)
.Where(k => state != -1 ? k.state == state : k.state > state)
.Where(k => poolName != null ? k.pool_name == poolName : k.pool_name != null)
.Where(k => submitter != null ? k.submitter == submitter : k.submitter != null);
jobs = jobs.OrderByDescending(job => job.id);
total = jobs.Count();
// Apply paging...
if (request.Page > 0)
{
jobs = jobs.Skip((request.Page - 1) * request.PageSize);
}
jobs = jobs.Take(request.PageSize);
foreach (var job in jobs)
{
summarylist.Add(new Summary(job));
}
}
var result = new DataSourceResult()
{
Data = summarylist,
Total = total
};
return Json(result, JsonRequestBehavior.AllowGet);
}
additional parameters are the current values which the user has set over the widget datepicker, input box etc.
Below is how my datasource looks like in grid:
<script type="text/javascript">
j$ = jQuery.noConflict();
j$(document).ready(function () {
j$("#grid").kendoGrid({
dataSource: {
transport: {
read: {
url: "/Home/GetData/",
dataType: "json",
data: {
startDate: j$("#startdate").val(),
endDate: j$("#enddate").val()
}
}
},
pageSize: 30,
serverPaging: true,
schema: {
data: 'Data',
total: 'Total'
}
},
height: j$(window).height() - 85,
groupable: true,
sortable: true,
filterable: false,
columnMenu: true,
pageable: true,
columns: [
{ field: "JobId", title: "Job Id", template: '#:JobId#', type: "number" },
{ field: "Name", title: "Job Name", hidden: true },
{ field: "PoolName", title: "Pool Name" },
{ title: "Date Time", columns: [{ field: "Start", title: "Start" },
{ field: "End", title: "End" }
],
headerAttributes: {
"class": "table-header-cell",
style: "text-align: center"
}
},
{ field: "State", title: "State" },
{
title: "Result", columns: [{ field: "ResultPassed", title: "P" },
{ field: "ResultFailed", title: "F" }
],
headerAttributes: {
"class": "table-header-cell",
style: "text-align: center"
}
},
{ field: "Submitter", title: "Submitter" }
]
});
});
</script>
It works pretty good until I observed this issue:
Change the filter values i.e submitter, date range etc and
controller gets all this information in additional parameters where
I am taking action accordingly and it works just fine.
Now suppose the result returned from step 1 has multiple pages and
when you click next page, or last page or any other page number, the
controller gets invoked which is expected but the additional
parameters being set in step 1 is not getting passed again instead
the default values are there which is ruining everything.
Correction:
Additional parameters are getting lost at client side only.
Now please tell me what am I missing here?
Expected Result: In step 2 additional parameters should not get lost and it should be same as step 1.
Any help is appreciated.
EDITED:
Complete controller and grid code.
Thanks,
Vineet
I got the solution from telerik support team:
Reply:
The described undesired behavior can be caused by the fact that the additional parameters:
data: {
startDate: j$("#startdate").val(),
endDate: j$("#enddate").val()
}
... are set to objects, instead of a functions. If they are set as functions, the values of the corresponding inputs will be evaluated every time read() is called, and the current values will be passed (like shown in the second example in the API reference):
http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#configuration-transport.read.data
I am using Kendo grid and want to validate one field's min value by another field from same record.
Meaning my data is like this :-
var courses = [{
CourseID : 1,
CourseName : "iPhone",
MinAge: 12,
MaxAge : 22,
MinAgeThreshold : 10,
MaxAgeThreshold : 30,
StartDate: "12/10/2014",
},
{
CourseID : 2,
CourseName : "Android",
MinAge: 12,
MaxAge : 22,
MinAgeThreshold : 10,
MaxAgeThreshold : 30,
StartDate: "12/10/2014",
}]
and I want to use MinAgeThreshold value in MinAge's validation min value, something like this:-
schema: {
model: {
id: "CourseID",
fields: {
CourseID: { editable: false, nullable: true },
StartDate: { editable: false, nullable: true },
CourseName: { editable: false, nullable: true },
MinAgeThreshold: { editable: false, nullable: true },
MinAge: { type: "number", validation: { required: true, min: MinAgeThreshold} },
MaxAge: { type: "number", validation: { required: true, min: 1} },
}
Is this possible somehow?
I tried to use in validation custom function like this
MinAge: {
type: "number",
validation: {
required: true,
minagevalidation: function (input) {
}
},
but I was not able to retrieve the values of MinAgeThreshold in minagevalidation function.
Any help would be greatly appreciated.
Regards
you can try something like given below to give the custom validation message and force the user to set value greater than the minimum value based on other input field in the same kendo grid.
MinAge: { type: "number",
validation: {
required: true,
MinAgevalidation: function (input) {
if(input.is("[name='MinAge']") &&(parseInt($("input[type='text'][name='MinAge']").val()) < parseInt($("input[type='text'][name='UnitPrice']").val()))){
input.attr("data-MinAgevalidation-msg", "MinAge should greater than MinAge threshold");
return false;
}
return true;
}
sample jsfiddle to set minimum value of one field based on other field's value .
I think I might have a solution for that kind of a problem. If you want to set the max of a field by the value of a different field you can add that to the grid edit method of your kendogrid.
var grid = $("#grid").kendoGrid({
edit: function(e){
if ( e.container.find("input[data-find='value:MinAge']).length != 0 ){
var numericTextBox = e.container.find("input[data-find='value:MinAge']).data("kendoNumericTextBox");
numericTextBox.min(e.model.MinAgeThreshold);
}
}
});
This will set the numerictTextBox of the MinAge input to min of the MinAgeThreshold that is in the dataItem of the row (model). That works with step, max, and so on as well. Edit is triggered when you enter the field. So if the initial value is 0 and your MinAgeThreshold is something else it will then switch to the MinAgeThreshold.
I have a project where I want to inline edit a value in a table generated via DataTables and am therefore using dataTables.editable
The table is rendering fine but when I try and to sumit an edit I get an error and if I look at the return value the id field is blank.
The controller action is as follows:
public ActionResult AjaxHandler(jQueryDataTableParamModel param)
{
var allMonthlyCosts = _unitOfWork.MonthlyCostRepository.Get(includeProperties: "Period, Employee");
IEnumerable<MonthlyCost> filteredMonthlyCosts;
if (!string.IsNullOrEmpty(param.sSearch))
{
filteredMonthlyCosts = _unitOfWork.MonthlyCostRepository.Get(includeProperties: "Period, Employee")
.Where(mc => mc.Period.Name.Contains(param.sSearch)
||
mc.Employee.ClockNo.Contains(param.sSearch));
}
else
{
filteredMonthlyCosts = allMonthlyCosts;
}
var displayedMonthlyCosts = filteredMonthlyCosts
.Skip(param.iDisplayStart)
.Take(param.iDisplayLength);
var result = from mc in displayedMonthlyCosts
select new { ID = mc.Id, EvisionCost = mc.EvisionCost, EmployeeNo = mc.Employee.ClockNo, PeriodName = mc.Period.Name, TotalDays = mc.TotalDays, TotalCost = mc.TotalCost() };
return Json(new
{
sEcho = param.sEcho,
iTotalRecords = allMonthlyCosts.Count(),
iTotalDisplayRecords = filteredMonthlyCosts.Count(),
aaData = result
},
JsonRequestBehavior.AllowGet);
}
The Javascript is as follows:
$('#myDataTable').dataTable({
"bServerSide": true,
"sAjaxSource": "MonthlyCost/AjaxHandler",
"bProcessing": true,
"aoColumns": [
{ "mData": "ID",
"bSearchable": false,
"bSortable": false,
"bVisible": false
},
{ "mData": "EvisionCost" },
{ "mData": "PeriodName" },
{ "mData": "EmployeeNo" },
{ "mData": "TotalDays" },
{ "mData": "TotalCost" }
]
}).makeEditable({
sUpdateURL: "/MonthlyCost/UpdateData",
"aoColumns": [
{},
null,
null,
null,
null]
});
The error I get is:
Cell cannot be #Updated(Server Error)
And the returned form is as follows:
value:2505
id:
rowId:0
columnPosition:0
columnId:1
columnName:EvisionCost
Issue is quite st.forward
Your editing is not reaching this plug-in code below . Thats why its throwing the error of your mention
CODE IN EDITABLE DATATABLE PLUGIN:
//Utility function used to apply editable plugin on table cells
function fnApplyEditable(aoNodes) {
var oDefaultEditableSettings = {
event: 'dblclick',
"callback": function (sValue, settings) {
properties.fnEndProcessingMode();
if (sNewCellValue == sValue) {
var aPos = oTable.fnGetPosition(this);
oTable.fnUpdate(sValue, aPos[0], aPos[2]);
} else {
var aPos = oTable.fnGetPosition(this);
oTable.fnUpdate(sOldValue, aPos[0], aPos[2]);
properties.fnShowError(sValue, "update");
}
},
"submitdata": function (value, settings) {
properties.fnStartProcessingMode();
sOldValue = value;
sNewCellValue = $("input,select", $(this)).val();
var id = fnGetCellID(this);
var rowId = oTable.fnGetPosition(this)[0];
var columnPosition = oTable.fnGetPosition(this)[1];
var columnId = oTable.fnGetPosition(this)[2];
var sColumnName = oTable.fnSettings().aoColumns[columnId].sName;
if (sColumnName == null || sColumnName == "")
sColumnName = oTable.fnSettings().aoColumns[columnId].sTitle;
return {
"id": id,
"rowId": rowId,
"columnPosition": columnPosition,
"columnId": columnId,
"columnName": sColumnName
};
},
"onerror": function () {
properties.fnEndProcessingMode();
properties.fnShowError("Cell cannot be updated(Server error)", "update");
},
"height": properties.height
};
This issue i am facing recently and i am trying like
<script type="text/javascript">
$(document).ready(function () {
$('#myDataTable').dataTable({ "bProcessing": true,
**"bServerSide": true,
"sAjaxSource": 'Home/AjaxHandler',
"sUpdateURL": '#Url.Action("UpdateData","Home")',
"sAddURL": '#Url.Action("AddData","Home")' ,
"sDeleteURL": '#Url.Action("DeleteData","Home")',**
"aoColumns": [
{ "sName": "ID",
"bSearchable": false,
"bSortable": false,
"bVisible": false
},
{ "sName": "Contact_Name" },
{ "sName": "Contact_Address" },
{ "sName": "Lead_Source" },
{ "sName": "Domain" },
]
}).makeEditable();
});
</script>
}
If this work please let me know . If you find any other way around do mention it . I am also in the same situation like you Finding answers
Regards
#Oleg - I am new to jqGrid.I have three issues. Urgent help required.
I am using jqGrid 3.8, inline edit mode.
I want to retain the invalid cell values after the pop up for invalid cell.
Also I want to set the focus back to the invalid cell.
I have "add row" and filter tool bar feature in my jqGrid. I have used Oleg's solution in creating drop down for filter tool bar (posted in another jQuery thread).
**
- Problem:
** I am calling setSearchSelect from afterSaveCell, because I want to add new values in filter drop down every time I add or delete column.(Note: column is a textbox). But the filter tool bar isn't getting refreshed even if I use
var sgrid = $("#list")[0];
sgrid.triggerToolbar();
See the code below for setting the toolbar.
<script type="text/javascript">
var mydata = [
{id:"1", Name:"Miroslav Klose", Category:"sport", Subcategory:"football"},
{id:"2", Name:"Michael Schumacher", Category:"sport", Subcategory:"formula 1"},
{id:"3", Name:"Albert Einstein", Category:"science", Subcategory:"physics"},
{id:"4", Name:"Blaise Pascal", Category:"science", Subcategory:"mathematics"}
],
grid = $("#list"),
getUniqueNames = function(columnName) {
var texts = grid.jqGrid('getCol',columnName), uniqueTexts = [],
textsLength = texts.length, text, textsMap = {}, i;
for (i=0;i<textsLength;i++) {
text = texts[i];
if (text !== undefined && textsMap[text] === undefined) {
// to test whether the texts is unique we place it in the map.
textsMap[text] = true;
uniqueTexts.push(text);
}
}
return uniqueTexts;
},
buildSearchSelect = function(uniqueNames) {
var values=":All";
$.each (uniqueNames, function() {
values += ";" + this + ":" + this;
});
return values;
},
setSearchSelect = function(columnName) {
grid.jqGrid('setColProp', columnName,
{
stype: 'select',
searchoptions: {
value:buildSearchSelect(getUniqueNames(columnName)),
sopt:['eq']
}
}
);
};
grid.jqGrid({
data: mydata,
datatype: 'local',
colModel: [
{ name:'Name', index:'Name', width:200 ,editable:true},
{ name:'Category', index:'Category', width:200,editable:true },
{ name:'Subcategory', index:'Subcategory', width:200,editable:true }
],
sortname: 'Name',
viewrecords: true,
rownumbers: true,
sortorder: "desc",
editurl: "clientArray",
multiselect: true,
pagination:true,
cellEdit: true,
cellsubmit: 'clientArray',
//ignoreCase: true,
pager: '#pager',
height: "auto",
enableSearch: true,
caption: "How to use filterToolbar better locally",
afterSaveCell: function(rowid,name,val,iRow,iCol) {
setSearchSelect(name);
jQuery("#list").('setColProp', name,
{
width:100
}
);
var sgrid = $("#list")[0];
sgrid.triggerToolbar();
alert(name);
},
loadComplete: function () {
setSearchSelect('Category');
}
}).jqGrid('navGrid','#pager',
{edit:false, add:false, del:false, search:false, refresh:true});
setSearchSelect('Category');
setSearchSelect('Subcategory');
grid.jqGrid('setColProp', 'Name',
{
searchoptions: {
sopt:['cn'],
dataInit: function(elem) {
$(elem).autocomplete({
source:getUniqueNames('Name'),
delay:0,
minLength:0
});
}
}
});
grid.jqGrid('filterToolbar',
{stringResult:true, searchOnEnter:true, defaultSearch:"cn"});
function addRow(tableId){
var loopRow = document.getElementById("addRowsInput").value;
var recordCount = '';
var rwData = '';
//var selRowIds = getRowIDs('list');
var gridProducts = $("#list");
var resetFirstRow = jQuery("#list").getRowData( 1 );
jQuery("#list").setRowData( 1, resetFirstRow );
if(loopRow == null || loopRow == "" || loopRow == "Enter number of units to be added")
{
loopRow = 1;
}
for(i=0; i< loopRow; i++)
{
recordCount = jQuery("#list").getGridParam("records") ;
var emptydata = [
{id:(recordCount+1), Name:"", Category:"", Subcategory:""}]
gridProducts.jqGrid('addRowData', recordCount+1, emptydata[0]);
}
}
</script>
#Oleg - one more question on the solution you suggested. Sorry I tried myself to find it but couldn't.
In the buildSearchSelect: method , how can I include filter for empty string.
As explained above I have a "Add Row" button. So when the user wants to filter rows with empty columns I need a filter value.
The implementation of setSearchSelect function from my old answer work only if the searching toolbar not yet exist. If the toolbar exist one have to modify the options of the select element or autocomplete source of the jQuery UI autocomplete widget.
I extended the code. You can see the new version of the demo here. In the same way one could use inline editing instead of the cell editing.
Here is the modified JavaScript code:
var mydata = [
{id:"1", Name:"Miroslav Klose", Category:"sport", Subcategory:"football"},
{id:"2", Name:"Michael Schumacher", Category:"sport", Subcategory:"formula 1"},
{id:"3", Name:"Albert Einstein", Category:"science", Subcategory:"physics"},
{id:"4", Name:"Blaise Pascal", Category:"science", Subcategory:"mathematics"}
],
grid = $("#list"),
getUniqueNames = function(columnName) {
var texts = grid.jqGrid('getCol',columnName), uniqueTexts = [],
textsLength = texts.length, text, textsMap = {}, i;
for (i=0;i<textsLength;i++) {
text = texts[i];
if (text !== undefined && textsMap[text] === undefined) {
// to test whether the texts is unique we place it in the map.
textsMap[text] = true;
uniqueTexts.push(text);
}
}
uniqueTexts.sort();
return uniqueTexts;
},
buildSearchSelect = function(uniqueNames) {
var values=":All";
$.each (uniqueNames, function() {
values += ";" + this + ":" + this;
});
return values;
},
setSearchSelect = function(columnName) {
var $select = $('select#gs_'+columnName), un = getUniqueNames(columnName),
htmlForSelect = '<option value="">All</option>', i, l=un.length, val;
grid.jqGrid('setColProp', columnName,
{
stype: 'select',
searchoptions: {
value:buildSearchSelect(un),
sopt:['eq']
}
}
);
if ($select.length > 0) {
// The searching toolbar already exist. One have to update it manually
for (i=0;i<l;i++) {
val = un[i];
htmlForSelect += '<option value="'+val+'">'+val+'</option>';
}
$select.html(htmlForSelect);
}
},
setAutocomplete = function(columnName) {
var $input = $('input#gs_'+columnName), un = getUniqueNames(columnName);
grid.jqGrid('setColProp', columnName,
{
searchoptions: {
sopt:['cn'],
dataInit: function(elem) {
$(elem).autocomplete({
source:un,
delay:0,
minLength:0
});
}
}
});
if ($input.length > 0) {
// The searching toolbar already exist. One have to update the source
$input.autocomplete('option', 'source', un);
}
},
selectColumns = ['Category','Subcategory'], autocompleteColumns = ['Name'];
grid.jqGrid({
data: mydata,
datatype: 'local',
colModel: [
{ name:'Name', index:'Name', width:200 ,editable:true},
{ name:'Category', index:'Category', width:200,editable:true },
{ name:'Subcategory', index:'Subcategory', width:200,editable:true }
],
sortname: 'Name',
viewrecords: true,
rownumbers: true,
sortorder: "desc",
cellEdit: true,
cellsubmit: 'clientArray',
ignoreCase: true,
pager: '#pager',
height: "auto",
caption: "How to use filterToolbar better locally including local cell editing",
afterSaveCell: function(rowid,name,val,iRow,iCol) {
if ($.inArray(name,selectColumns) !== -1) {
setSearchSelect(name);
} else if ($.inArray(name,autocompleteColumns) !== -1) {
setAutocomplete(name);
}
}
}).jqGrid('navGrid','#pager',
{edit:false, add:false, del:false, search:false, refresh:true});
$.each(selectColumns,function() {
setSearchSelect(String(this));
});
$.each(autocompleteColumns,function() {
setAutocomplete(String(this));
});
grid.jqGrid('filterToolbar',
{stringResult:true, searchOnEnter:true, defaultSearch:"cn"});