JqPivot and data load by ajax - jqgrid

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).

Related

Ajax - Parse oData Response

I have an ajax call that gets data from a REST api.
$.ajax({
url: "http://localhost:52139/odata/WEB_V_CIVIC_ADDRESS",
data: { enteredText: "'" + $('#addressTextField').val() + "'" },
type: "GET",
dataType: 'json',
ContentType: "application/json",
success: function (data) {
alert(JSON.stringify(data));
response($.map(data.accountaddressList, function (item) {
return {
item: item.civicaddress,
value: item.accountNumber,
label: item.civicaddress
}
}));
},
error: function (data, xml, errorThrown) {
alert('Error loading address list: ' + errorThrown);
}
});
The odata returned from that call looks like:
{
"#odata.context":"http://localhost:52139/odata/$metadata#WEB_V_CIVIC_ADDRESS/AValues.Classes.Entities.AccountAddress","value":[
{
"#odata.type":"#AValues.Classes.Entities.AccountAddress","accountNumber":88887,"rowNumber":0,"civicaddress":"123 Fake St"
},{
"#odata.type":"#AValues.Classes.Entities.AccountAddress","accountNumber":88888,"rowNumber":0,"civicaddress":"321 Faker St"
}
]
}
So the current code throws an 'Undefined' error on the line: response($.map(data.accountaddressList, function (item) {
How do I map the 'civicaddress' and 'accountNumber' from each value in the odata response to 'item'?
Thanks.
I got it, needed to change it to response($.map(data.value, function (item)

DataTables: Custom Response Handling

I started working on AngularJS and DataTables and wonder whether it is possible to customize the response DataTables is expecting. The current expectation of the DataTables plugin is something like this:
{
"draw": 1,
"recordsTotal": 57,
"recordsFiltered": 5,
"data": [...]
}
On the server end, the API's are being handled by django-tastypie
The response from server is:
{
meta: {
limit: 20,
next: null,
offset: 0,
previous: null,
total_count: 2
},
objects: [...]
}
So, is there a way to tweak Datatables Plugin to accept/map this response, or I'll have to find a way to add expected fields to the api?
So far I've done this:
var deptTable = angular.element('#deptManagementTable').DataTable({
processing: true,
serverSide: true,
pagingType: "simple_numbers",
ajax: {
url: "/client/api/v1/departments/",
data: function(d) {
d.limit = d.length;
d.offset = d.start;
d.dept_name__icontains = d.search.value;
},
dataSrc: function(json) {
for (var i=0, len=json.objects.length ; i<len ; i++) {
json.objects[i].DT_RowId = json.objects[i].dept_id;
}
return json.objects;
}
},
aLengthMenu: [
[5, 25, 50, 100],
[5, 25, 50, 100]
],
iDisplayLength: 5,
columns: [
{
data: "dept_name"
},
{
data: "dept_created_on",
render: function ( data, type, full, meta ) {
var dateCreated = new Date(data);
dateCreated = dateCreated.toLocaleDateString();
return dateCreated;
}
}
]
});
Any help will be appreciated.
Thanks in Advance :)
You can pass a function to the DataTables ajax option, this will give you full control over how to fetch and map the data before passing it to DataTables.
.DataTable({
serverSide: true,
ajax: function(data, callback, settings) {
// make a regular ajax request using data.start and data.length
$.get('/client/api/v1/departments/', {
limit: data.length,
offset: data.start,
dept_name__icontains: data.search.value
}, function(res) {
// map your server's response to the DataTables format and pass it to
// DataTables' callback
callback({
recordsTotal: res.meta.total_count,
recordsFiltered: res.meta.total_count,
data: res.objects
});
});
}
});
The solution above has been tested with jQuery DataTables 1.10.4.
As this question is tagged with Angular, here's a solution for those using angular-datatables.
<div ng-controller="testCtrl">
<table datatable dt-options="dtOptions" dt-columns="dtColumns" class="row-border hover"></table>
</div>
.controller('testCtrl', function($scope, $http, DTOptionsBuilder, DTColumnBuilder) {
$scope.dtOptions = DTOptionsBuilder.newOptions()
.withOption('serverSide', true)
.withOption('ajax', function(data, callback, settings) {
// make an ajax request using data.start and data.length
$http.get('/client/api/v1/departments/', {
limit: data.length,
offset: data.start,
dept_name__icontains: data.search.value
}).success(function(res) {
// map your server's response to the DataTables format and pass it to
// DataTables' callback
callback({
recordsTotal: res.meta.total_count,
recordsFiltered: res.meta.total_count,
data: res.objects
});
});
})
.withDataProp('data'); // IMPORTANT¹
$scope.dtColumns = [
// your column definitions here
];
});
The solution above has been tested with angular-datatables 0.3.0 + DataTables 1.10.4.
¹ The important part to note here is that the angular-datatables solution requires .withDataProp('data') to work, while the pure jQuery DataTables solution does not have a data: 'data' option.
This answer was very useful, but seems a bit outdated in the context of the current (1.10.12 at the moment) version of datatables, which actually makes life a lot easier (or at least more readable).
Under the current version you can do something like the following in your declaration (bearing in mind that tastypie needs to have the filterable & ordering options set for the fields you want to use).
You can now access the data being submitted in the ajax request by doing data.attr inside the function.
This assumes you wish to restrict searching to one field, but can easily be extended in the same manner do console.log(data) within the ajax function to see what is sent.
var table = $('#tableName').DataTable({
"deferRender":true,
"serverSide": true,
"ajax": function(data, callback, settings) {
var sort_column_name = data.columns[data.order[0].column].data.replace(/\./g,"__");
var direction = "";
if (data.order[0].dir == "desc") { direction = "-"};
$.get('your/tasty/pie/url?format=json', {
limit: data.length,
offset: data.start,
your_search_field__searchattr: data.search.value,
order_by: direction +sort_column_name
}, function(res) {
callback({
recordsTotal: res.meta.total_count,
recordsFiltered: res.meta.total_count,
data: res.objects
});
});
},
"columns": [
{ "data":"column_1", "orderable": false },
{ "data":"column_2" },
{ "data":"column_3" }
],
"order": [[1, "asc"]]
});

SELECT2 ajax - preloaded options

At the moment I have a dropdown that works with ajax request to the server, but it also be nice to attach some default options on select2 initialization. With initSelection function I only can attach one option, but not full preloaded array. I was also trying to use data option but it's doesn't work too.
Here is my code:
$("#address-select2").select2({
placeholder: "--- ' . t('I\'ll add new address') . ' ---",
minimumInputLength: 3,
ajax: {
url: "/ajax/address_autocomplete/from",
dataType: "json",
type: "POST",
data: function (term, page) {
return {
q: term
};
},
results: function (data, page) {
return {results: data.addresses};
}
},
initSelection: function (element, callback) {
$.ajax("/ajax/address_autocomplete/from/100", {
dataType: "json"
}).done(function(data) {
callback(data.addresses[0]);
});
},
formatResult: function (address) {
return "<span class=\"dropdown-element\">" + address.text + "</span>";
},
formatSelection: function (address) {
return address.text;
},
formatNoMatches: function () { return "' . t('No result found!') . '";},
formatSearching: function () { return "' . t('Searching...') . '"; },
formatLoadMore: function (pageNumber) { return "' . t('Loading results...') . '"; },
dropdownCssClass : "bigdrop"
});
please do not pass callback(data.addresses[0]);
please pass array directly like this callback(data.addresses);
it should work i have done it.

Automatically cancelling jqgrid request

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").

JSON, jQueryUI Autocomplete, AJAX - Cannot get data when array is not local

I have searched stackoverflow, as well as the web for some insight into how to get the jQueryUI Autocomplete plugin working with my JSON data, and I'm at a loss. I had it working like a charm with a local data array. I was able to pull values and build html.
I ran into a problem when I had to pull JSON form this source:
/Search/AjaxFindPeopleProperties2
?txtSearch=ca pulls up the test data that I am trying to loop through, when I type in 'ca' to populate the autocomplete list. One of the problems is that ?term=ca is appended to the url instead of ?txtSearch=ca and I'm not sure how to change it.
This is an example of the data:
{
"MatchedProperties": [
{
"Id": 201,
"Name": "Carlyle Center",
"Description": "Comfort, convenience and style are just a few of the features you'll ...",
"ImageUrl": "/Photos/n/225/4989/PU__ThumbnailRS.jpg"
}
]
}
...and here is the ajax call I'm trying to implement:
$(document).ready(function () {
val = $("#txtSearch").val();
$.ajax({
type: "POST",
url: "/Search/AjaxFindPeopleProperties2",
dataType: "json",
data: "{}",
contentType: "application/json; charset=utf-8",
success: function (data) {
$('#txtSearch').autocomplete({
minLength: 0,
source: data.d, //not sure what this is or if it's correct
focus: function (event, ui) {
$('#txtSearch').val(ui.item.MatchedProperties.Name);
$.widget("custom.catcomplete", $.ui.autocomplete, {
//customize menu item html here
_renderItem: function (ul, item) {
return $("<li class='suggested-search-item" + " " + currentCategory + "'></li>")
.data("item.autocomplete", item)
.append($("<a><img src='" + item.MatchedProperties.ImageUrl + "' /><span class='name'>" + item.MatchedProperties.Name + "</span><span class='location'>" + "item.location" + "</span><span class='description'>" + item.MatchedProperties.Description + "</span></a>"))
.appendTo(ul);
},
_renderMenu: function (ul, items) {
var self = this,
currentCategory = "Properties Static Test Category";
$.each(items, function (index, item) {
if (item.category != currentCategory) {
ul.append("<li class='suggested-search-category ui-autocomplete-category'>" + currentCategory + "</li>");
//currentCategory = item.category;
}
self._renderItem(ul, item);
});
}
}//END: widget
//return false;
},
select: function (event, ui) {
$('#txtSearch').val(ui.item.MatchedProperties.Name);
//$('#selectedValue').text("Selected value:" + ui.item.Abbreviation);
return false;
}
});
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(textStatus);
}
}); //END ajax
}); //END: doc ready
and I'm initializing here:
<script type="text/javascript">
//initialize autocomplete
$("#txtSearch").autocomplete({ //autocomplete with category support
/*basic settings*/
delay: 0,
source: "/Search/AjaxFindPeopleProperties2",
autoFocus: true,
minLength: 2 //can adjust this to determine how many characters need to be entered before autocomplete will kick in
});
//set auto fucus
$("#txtSearch").autocomplete("option", "autoFocus", true);
</script>
any help would be great...
Thanks!

Resources