Automatically cancelling jqgrid request - ajax

I'm aware of this answer: How do I add a cancel button to my jqgrid?, and I'm attempting to implement something similar, although without a button to trigger the cancel. Iv'e got a grid that loads on page load (a search that by default loads with no criteria) and I'd like to be able to cancel that default empty criteria search when the user actually executes a search with criteria. Since I don't need a button I'm trying to simplify the solution by merely keeping track of the xhr request in the loadBeforeSend method, and abort that xhr if it is not null as I load the grid. Code:
var gridXhr;
function getGridData() {
var searchParms = ...;
var colHeaders = [...];
var colDefinitions = [...];
if (gridXhr != null) {
alert(gridXhr.readyState);
gridXhr.abort();
gridXhr = null;
}
$('#grid').jqGrid('GridUnload');
$('#grid').jqGrid({
defaults: {...},
autowidth:true,
url: "<%= Page.Request.Path %>/ExecuteSearch",
mtype: 'POST',
ajaxGridOptions: { contentType: "application/json" },
postData: searchParms,
datatype: "json",
prmNames: {
nd: null,
rows: null,
page: null,
sort: null,
order: null
},
jsonReader: {
root: function (obj) { return obj.d; },
page: function (obj) { return 1; },
total: function (obj) { return (obj.d.length / 20); },
records: function (obj) { return obj.d.length; },
id: 'CatalogID',
cell: '',
repeatitems: false
},
loadonce: true,
colNames: colHeaders,
colModel: colDefinitions,
caption: "Search Results",
pager: 'searchPaging',
viewrecords: true,
loadBeforeSend: function (xhr) {
gridXhr = xhr;
},
loadError: function (xhr, status, error) {
gridXhr = null;
if (error != 'abort') {
alert("Load Error:" + status + "\n" + error);
}
},
loadComplete: function() {
gridXhr = null;
},
multiselect: <%= this.MultiSelect.ToString().ToLower() %>,
multiboxonly: true
}).setGridWidth(popWidth);
}
The problem I'm having is that subsequent executions of the jqGrid don't work. The loadError function is triggered, with an error (3rd parameter) of "abort." Do I need to do something more/different with the loadBeforeSend as done in the other answer?
Also, Oleg mentioned in his sample code myGrid[0].endReq(); and I can find no mention of that in the documentation - does that function exist?

If I understand you correctly you need just change the line
datatype: "json",
to something like
datatype: isSearchParamEmpty(searchParms) ? "local" : "json",
In other words you should create grid with datatype: "local" instead of datatype: "json" in case of empty searching criteria. The grid will stay empty.
Additionally you should consider to create jqGrid only once if colDefinitions and colHeaders will stay unchanged for different searching criteria. Instead of recreating of the grid you could change postData only and call trigger("reloadGrid").

Related

Change Kendo Grid Cell With Ajax Response When Another Cell Changes

Using a Kendo grid with 3 columns, I have an event that fires when the first column is changed that makes an ajax call and returns some data. I want to update the second column with the returned data but I'm not having any luck and I'm not even sure if this is the correct approach. I can change the second column with static data by adding a change event to my datasource of my grid, but that of course doesn't help. The only examples I can seem to find show changing another column with client side data, not data returned from the server. Here's what I have so far:
$("#manualStatsGrid").kendoGrid({
dataSource: this.GetManualStatisticsDataSource(),
sortable: true,
pageable: false,
filterable: true,
toolbar: ["create"],
editable: "inline",
messages: {
commands: {
create: "Add New Statistic"
}
},
edit: function (e) {
var _this = _manualStats;
var input = e.container.find(".k-input");
var value = input.val();
input.keyup(function(){
value = input.val();
});
$("[name='Statistic']", e.container).blur(function(){
var input = $(this);
$("#log").html(input.attr('name') + " blurred " + value);
//valid the GL account number
$.ajax({
type: "GET",
url: _this.ValidateGlUrl,
dataType: 'json',
data: { glNumber: value },
success: function (response) {
var newDescription = response.Data.description;
console.log(newDescription);
//change description column here?
},
error: function (response) {
console.log(response);
}
});
});
},
columns: [
{ field: "Statistic" },
{ field: "Description" },
{ field: "Instructions" },
{ command: ["edit", "destroy"], title: " ", width: "250px"}
]
});
}
this.GetManualStatisticsDataSource = function () {
var _this = _manualStats;
var dataSource = {
type: "json",
transport: {
read: {
type: "POST",
url: _this.GetManualStatisticsUrl,
dataType: "json"
},
update: {
type: "POST",
url: _this.UpdateManualStatisticsUrl,
dataType: "json"
},
create: {
type: "POST",
url: _this.CreateManualStatisticsUrl,
dataType: "json"
},
destroy: {
type: "POST",
url: _this.DeleteManualStatisticsUrl,
dataType: "json"
}
},
schema: {
model: {
id: "Statistic",
fields: {
Statistic: {
type: "string",
editable: true,
validation: { required: true, pattern: "[0-9]{5}.[0-9]{3}", validationmessage: "Please use the following format: #####.###" }
},
Description: { editable: false },
Instructions: { type: "string", editable: true }
}
}
}
Inside the edit event, you have e.model. The model has the method set() which can change any dataItem's property value:
edit: function (e) {
...
var editEvent = e; // Creates a local var with the edit's event 'e' variable to be available inside the 'blur' event
$("[name='Statistic']", e.container).blur(function() {
...
$.ajax({
...
success: function(e, response) { // 'e' inside this callback is the 'editEvent' variable
e.model.set("Description", response.Data.description); // e.model.set() will change any model's property you want
}.bind(null, editEvent) // Binds the 'editEvent' variable to the success param
});
});
Working demo
Made this snippet of top of my head. Tell me if there is something wrong with it.

JqPivot and data load by ajax

Can someone post a demo or a piece of code, to exemplify how to use jqpivot and loading data using ajax.
Thank you.
I would recommend you to examine the source code of free jqGrid. Look at the part of the code. It looks like
jqPivot: function (data, pivotOpt, gridOpt, ajaxOpt) {
return this.each(function () {
var $t = this, $self = $($t), $j = $.fn.jqGrid;
function pivot(data) {
...
}
if (typeof data === "string") {
$.ajax($.extend({
url: data,
dataType: "json",
success: function (data) {
pivot(jgrid.getAccessor(data, ajaxOpt && ajaxOpt.reader ? ajaxOpt.reader : "rows"));
}
}, ajaxOpt || {}));
} else {
pivot(data);
}
});
}
You will get practically directly the answer on your question. You need specify the URL to the server which provides the input data in JSON form. No other data format is supported ("xml", "jsonp" and so on) directly, but you can use ajaxOpt parameter to overwrite the parameters of the Ajax call. It's important to understand additionally, that jqGrid uses $.jgrid.getAccessor method to read the data from the server response. The default data format should be the following:
{
"rows": ...
}
where the value of "rows" should have the same format as the data parameter of jqPivot if you use if without Ajax. If you have for example
{
{
"myRoot": {
"myData": ...
}
}
}
then you can use 4-th parameter of jqPivot (ajaxOpt) as
{ reader: "myRoot.myData" }
If the response from the server is array of data:
[
...
]
or it have some non-standard form than you can use function form of reader. For example
$("#grid").jqGrid("jqPivot", "/myUrl", {
xDimension: [{...}],
yDimension: [{...}, ...],
aggregates: [{...}],
},
{
iconSet: "fontAwesome",
cmTemplate: { autoResizable: true, width: 80 },
shrinkToFit: false,
autoResizing: { compact: true },
pager: true,
rowNum: 20,
rowList: [5, 10, 20, 100, "10000:All"]
},
{
reader: function (obj) { return obj; },
contentType: "application/json; charset=utf-8",
type: "POST",
error: function (jqXHR, textStatus, errorThrown) {
alert('HTTP status code: ' + jqXHR.status + '\n' +
'textStatus: ' + textStatus + '\n' +
'errorThrown: ' + errorThrown);
alert('HTTP message body (jqXHR.responseText): ' + '\n' + jqXHR.responseText);
}
});
The above code specify the reader at the function which use all the response data directly (without object with rows property). It specifies contentType and type parameter of the jQuery.ajax and the callback function error.
If all the options seems you too difficult you can load the data directy in your code with direct call of jQuery.ajax for example and the call jqPivot after the data are loaded (inside of success callback or done).

jQuery ui autocomplte in jQGrid popup position issue

I have following code in jQgrid and I am using jQuery ui autocomplete in one of the field. But the pop up of autocomplete displays somewhere else as shown in figure. From IE developer tools I noticed the results are attached to body tag, which is at the end of the page. I tried using appendTo, but that doesn't help.
{
name: 'nameAccount',
index: 'nameAccount',
width: 300,
editable: true, sortable: false, resizable: false,
shrinkToFit: true
,editoptions: {
dataInit: function (elem) {
var autocompleteSource = function(request, response,term) {
var param = request.term;
$.ajax({
url: myUrl,
contentType: "application/json; charset=utf-8",
dataType: "json",
type: "GET",
success: function (myyydata) {
//alert('HI-Success');
//response( myyydata );
response($.map(myyydata, function (item) {
return {
label: item.AccountInfo,
value: item.AccountInfo
}
}));
} ,
error: function (res, status) {
alert('HI-error');
//alert(res.status+" : "+res.statusText+". Status: "+status);
}
});//END AJAX
};
$(elem).autocomplete({
source: autocompleteSource,
//appendTo: "#"+elem.id,
position: { collision: "flip" },
minLength: 2
});//END AUOTOCOMPLETE
}//END Dataint
}//END Dataint
},
minnu4515. i guess it is because of the css misalignment. i faced the similar problem and i manually set the z-index alignmnet. that solved my issue.
$('.ui-autocomplete').css('zIndex',1000);

Object doesn't support this property or method jquery ie8

I have two variables in my script view page, one called products and the other sites.
I have declared them like that.
Add.cshtml View:
$(function () {
products;
sites;
GetProductsAndSites(productsURL, sitesURL, '#Model.Key', false);
});
I call an ajax function, in another .js file.
People.js
function GetProductsAndSites(productsURL, sitesURL, secondLevelSiteKey, flag) {
$.ajax({
type: "POST",
url: productsURL,
async: false,
success: function (returndata) {
if (returndata.ok) {
**products = returndata.dataNames;**
//var tempProducts = returndata.dataNames;
$('#select-product').autocomplete({
delay: 0,
minLength: 1,
source: returndata.dataNames,
select: function (event, ui)
{
$.ajax({
type: "POST",
url: sitesURL,
data: { "productID": selectedProductID, "siteID": secondLevelSiteKey },
async: false,
success: function (returndata) {
if (returndata.ok) {
//products = tempProducts ;
**sites = returndata.dataNames;**
$('#select-site').autocomplete({
delay: 0,
minLength: 1,
source: returndata.dataNames,
select: function (event, ui) {
$("#select-site").val(ui.item.label);
});
}
});
}
}
});
}
it throws "Object doesn't support this property or method" exception at (products = returndata.dataNames;) line...at first I thought it can not see the products vairalble, but then I realized that it can see the "sites" variable, so I commented the products line and expected that it would throw the same exception at the sites line, but it works just fine.
I have tried creating a local variable and store the returndata.dataNames in it instead of products vairalbe and then set products value before the sites line, but still it throws an exception. I tried to put the products line after the sites lines it threw the same exception at the products line also.
Help!
After searching and searching, I finally found my solution. Tested with IE8.
Override
if ('XDomainRequest' in window && window.XDomainRequest !== null) {
jQuery.ajaxSettings.xhr = function() {
try {
return new ActiveXObject("Microsoft.XMLHTTP");
}
catch(e) { }
jQuery.support.cors = true;
}
}
Make the ajax request
$.ajax({
type: 'GET',
url: "your-url",
async: true,
cache: false,
crossDomain: true,
contentType: 'application/json; charset=utf-8',
dataType: 'json'
})
.fail(function(jqXHR, textStatus, errorThrown) {
console.log('ERROR: ' + errorThrown);
})
.always(function() {
// Do stuff
});
For me this answer helped, where I detect the IE browser and if its lower than 7 or so then set ActiveXObject else XMLHttpRequest.
jQuery.ajaxSettings.xhr: function() {
// detect if IE and older versions of IE
if (jQuery.browser.msie && jQuery.browser.version.substr(0, 1) <= 7)
return new ActiveXObject("Microsoft.XMLHTTP");
else
return new XMLHttpRequest();
}
Reference:
Detect IE 7 or lower.
Difference between ActiveXObject and XMLHttpRequest.

Why loadComplete fires before gridComplete?

I am trying to manipulate the data fetched from the server in loadComplete event:
loadComplete:function(data){
alert("load completed");
$.each (data,function(index,item){
item["customerSite"]=item.header.customerName + ' / '+item.header.siteDescription;
});
}
The newly added field is meant to be used as a column to be grouped by
However I keep getting this column as undefined as grouping header. I tried adding another field to the JSON object as a regular column, the column ends up to be empty. As I was debugging I noticed the grid is constructed before my breakpoint in the loadComplete stops.
My understanding of the loadComplete event is that it will fired as soon as the ajax call has success return. After I introduced gridComplete event to my code, I noticed gridComplete is invoked before loadComplete is invoked.
gridComplete: function(){
alert("grid completed");
}
What I am doing wrong? I am using
jsonReader: {
repeatitems: false,
id: "id",
root: function (obj) { return obj; },
page: function (obj) { return 1; },
total: function (obj) { return 1; },
records: function (obj) { return obj.length; }
}
to process returned JSON string, but cannot imagine that might be the problem. Please help!
Base on Oleg's comment, I will use custom formatter. However the result of the fomratter does not work for the group header, which this column is for. If I set groupColumnShow : [true], the column's data is all correct, but still leaves the group header to be 'undefined'
Following grid's definition:
buildGrid:function(){
var myGrid = jQuery("#serverList");
myGrid.jqGrid({
datatype: "json",
url: "http://localhost:8080/cm.server/api/v1/agent/config.json?",
jsonReader: {
repeatitems: false,
id: "id",
root: function (obj) { return obj; },
page: function (obj) { return 1; },
total: function (obj) { return 1; },
records: function (obj) { return obj.length; }
},
colNames:['Customer/Site','Customer','Site','Server ID', 'Server Name', ,'id'],
colModel :[
{name:'customerSite',editable:false, formatter:that.buildCustmerSite},
{name:'header.customerName',hidden:true,editable:true,editrules:{edithidden:true},editoptions:{readonly:true,size:25},formoptions:{ rowpos:1,elmprefix:" "}},
{name:'header.siteDescription', hidden:true, editable:true,editrules:{edithidden:true},editoptions:{readonly:true,size:25},formoptions:{ rowpos:2,elmprefix:" "}},
{name:'header.serverID', index:'header.serverID', width:200, align:'right',editable:true,editoptions:{readonly:true,size:25},formoptions:{ rowpos:3,elmprefix:" "}},
{name:'header.serverName', index:'header.serverName', width:150, align:'right',editable:true,editoptions:{readonly:true,size:25},formoptions:{ rowpos:4,elmprefix:" "}},
{name:'id', hidden:true},
],
height: '500',
width: '100%',
rowNum:20,
autowidth: true,
pager: '#pager',
sortname: 'serverID',
sortorder: "desc",
viewrecords: true,
caption: 'Server Configurations',
editurl:"/cm.server/api/v1/agent/config-grid",
autoencode:true,
ignoreCase:true,
grouping:true,
groupingView:{
groupField:['customerSite'],
groupColumnShow : [false]
}
});
jQuery("#serverList").jqGrid('navGrid','#pager',
{edit:true,add:false,del:false,search:true},
{height:450,reloadAfterSubmit:true, recreateForm:true,jqModal:true, closeOnEscape:true, closeAfterEdit:true, bottominfo:"Fields marked with (*) are required"}, // edit options
{} // search options
);
jQuery("#serverList").jqGrid('filterToolbar');
return true;
}
and following is the custom formatter:
buildCustmerSite:function(cellvalue,options,rowObject){
var customerSite =rowObject.header['customerName'] + '/'+ rowObject.header["siteDescription"];
return customerSite;
}
There are small differences between loadComplate and gridComplete, but both will be called after the grid contain is prepared. So you can't just modify the data of the loadComplate to change the grid contain.
You don't posted the definition of your grid, so it is difficult to answer on your question exactly. What you probably want can be solved with respect of the custom formatter which you can define for the customerSite column. Inside of formatter function you have access to rowObject where you find source information to construct the customerName + ' / ' + siteDescription.

Resources