jqGrid + POST + default parameters + serializedGridData - json

I need to load my grid from a server that expect a URL + parameters + a serialized payload, i.e. the message body. I am using a POST method and the server expects this along with JSON payload.
The serialized payload is a JSON string for MongoDB that instructs mongo how to find the data we care about. I designed the RESTful interface to respond back in the JSON format that jqGrid expects, however, to use pagination, I expected jqGrid to append the values for "page", "rows", etc, etc as a query string: baseURL?rows=10&page=1
Here is my grid setup
grid.jqGrid({
ajaxGridOptions: {
contentType: "application/json",
},
altRows: true,
autoWidth: true,
caption: "Results for " + ADC_Idl.buildQueryTitle(),
colNames: displayNames,
colModel: columnModel,
datatype: "json",
height: "auto",
mtype: "POST",
pager: '#pager5',
//postData: ADC_Idl.buildQueryPayload(),
serializeGridData: function (postData) {
grid.jqGrid("setGridParam", "url", ADC_Idl.buildQueryURL() + "?" + jQuery.param(postData));
return ADC_Idl.buildQueryPayload();
},
beforeRequest: function() {
grid.jqGrid("setGridParam", "url", ADC_Idl.buildQueryURL() + "?page=" +
grid.jqGrid("getGridParam", "page") + "&rows=" +
grid.jqGrid("getGridParam", "rowNum") );
},
rowList: [10, 20, 30],
rowNum: 10,
url: ADC_Idl.buildQueryURL(),
viewrecords: true,
jsonReader: {
repeatitems: false
}
I've left a few things in there to show what I have tried. I tried having the serializedGridData function update the URL, with no luck, for whatever reason it seems to be ignored.
I tried updating the URL before the request, still no luck.
Originally I just set postData = serialized data, assuming the default pagination parameters would still be appended. This was not the case.
The documentation for postData just says "See API methods for manipulation" with no link (NO LINK IN A WIKI??!!! come on!!)
I've read every Oleg answer I could find here, nothing seems to address this scenario, which I find hard to understand, this must be a pretty common usecase.
This is how my server responds to the initial request for data (no pagination needed)
page: 1
records: 500
rows: [{_id: 1, REALM: "example.com", ACCOUNT: "8561000000",…},…]
total: 50
truncated for brevity.
After three days of trying everything I can think of, I'm pleading for some jqGrid experts to help!!
Thanks!
UPDATE
Figured it out and comments from Oleg made it even better. Posted as Answer!

Almost immediately after I posted this question I noticed something in another post from StackOverflow,
jqGrid("setGridParam"...
format is different for setting then getting, it excepts a hash for the update vs a parameter list for the get... UGH.
Once I fixed that, it worked!
Using some of the recommendations from Oleg's (thanks!) I have an even better solution as the code is cleaner and feels less hacky.
grid.jqGrid({
ajaxGridOptions: {
contentType: "application/json",
},
altRows: true,
autoWidth: true,
caption: "Results for " + ADC_Idl.buildQueryTitle(),
colNames: displayNames,
colModel: columnModel,
datatype: "json",
height: "auto",
gridview: true,
mtype: "POST",
pager: '#pager5',
postData: ADC_Idl.buildQueryPayload(),
beforeRequest: function() {
var gridParameters = jQuery(this).jqGrid("getGridParam");
var baseURL = gridParameters.url.split("?").shift();
var queryString = {
page: gridParameters.page,
rows: gridParameters.rowNum
};
gridParameters.url = baseURL + "?" + jQuery.param( queryString );
},
rowList: [10, 20, 30],
rowNum: 10,
url: ADC_Idl.buildQueryURL(),
viewrecords: true,
jsonReader: {
repeatitems: false,
id: "_id"
}
});
The relevant parts are:
postData: I use this to have jqGrid call my payload builder which returns JSON.stringify(payload object)
beforeRequest: Causes jqGrid to take the url used to define the grid with and remove any params already attached then update them with the newest values for page and rows.
jasonReader: added "id: "_id" as this is the key mongodb uses for the id.
gridview: true - This apparently speeds of the display of the grid? Oleg recommended, I did it, he's got a very detailed write up about it here: Oleg's explaination of gridview: true
It was also recommended that I provide my colModel, but I can't, this code is designed to build a jqGrid dynamically once the user submits a query that is directed at mongodb. The grid is built as a response to the users input, thus it is not something I have to share.

Related

Extjs is passing my cfc a json string that I can not read

I am playing with the ExtJs4 cartracker application written by existdisolve. I was able to change his queries from rest requests to ajax requests. I also modified the api calls to use ajax to make ajax requests for updates.
I am not getting form or url data passed to my cfc. Instead, in firebug I see JSON passed. I am confused if it is not passed in the form or the url, how is this passed and how do I get to the data? I have tried deserialized the form and url and dumping these after the deserialize and I am told that it is not json.
Where would I find the json?
I am not allowed to post a picture. But it looks like this in the xhr window:
JSON
Active true
ColorID null
Shortname red
Longname Blood Red
So if it is being passed why can I not get to it?
Edit:
#existdissolve - I replaced the rest.js with ajax.js which looks like this:
/**
* Abstract REST proxy
*/
Ext.define('CarTracker6.proxy.Ajax', {
extend: 'Ext.data.proxy.Ajax',
alias: 'proxy.baseajax',
/*format: 'json',*/
limitParam: 'max',
startParam: 'offset',
sortParam: 'sortorder',
writer : {
type : 'ajax',
encode : false,
writeAllFields : true,
root : 'data',
allowSingle : true,
batch : false,
method: 'post',
params: { record: 'record' },
writeRecords : function(request, data) {
request.jsonData = data;
return request;
}
},
reader: {
type: 'json',
root: 'data',
totalProperty: 'count'
},
api: {
read: 'api/option/colors.cfc?method=getcolors',
create: 'api/option/colors.cfc?method=addcolors',
update: 'api/option/colors.cfc?method=updatecolors',
destroy: 'api/option/colors.cfc?method=deletecolors'
}
});
My read works perfectly and I can call the correct cfcs for colors, statuses, etc. and retrieve the requisite data. I am looking to pass parameters to the CFCs and that is not working.
see http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.data.writer.Json-cfg-encode:
if the encode property of your writer is set to false, all data is sent as raw post body. Instead, you can use
encode: true,
root: 'data', // must be set if encode is true

How to extract data from Tumblr API (JSON)?

I have set up a Tumblr account and registered my application to authenticate it.
Tumblr Documentation: http://www.tumblr.com/docs/en/api/v2
I understand the API outputs JSON like this:
{
"meta": {
"status": 200,
"msg": "OK"
},
"response": {
"blog": {
"title": "David's Log",
"posts": 3456,
"name": "david",
"url": "http:\/\/david.tumblr.com\/",
"updated": 1308953007,
"description": "<p><strong>Mr. Karp<\/strong> is tall and skinny, with
unflinching blue eyes a mop of brown hair.\r\n
"ask": true,
"ask_anon": false,
"likes": 12345
}
}
}
Thats fine, but the documentation ends there. I have no idea how to get this information and display it on my site.
I thought the way you would get it would be something like:
$.ajax({
url: "http://api.tumblr.com/v2/blog/myblog.tumblr.com/info?api-key=myapikey",
dataType: 'jsonp',
success: function(results){
console.log(results);
}
});
But this does nothing.
Can anyone help me out? Thanks
results is now the object you can use to reference the JSON structure. When you console.log the results object, it should appear in the Javascript developer console where you can explore the object tree.
The response object
So when your success callback receives the response, the following should be available to you:
results.meta.status => 200
results.meta.msg => "OK"
results.response.title => "David's Log"
results.response.posts => 3456
results.response.name => "david"
results.response.url => "http://david.tumblr.com/"
results.response.updated => 1308953007
results.response.description => "<p><strong>Mr. Karp</strong>.."
results.response.ask => true
results.response.ask_anon => false
results.response.likes => 12345
Writing to the page
If you actually want to see something written to your page you'll need to use a function that modifies the DOM such as document.write, or, since you're using Jquery, $("#myDivId").html(results.response.title);
Try this:
Add <div id="myDivId"></div> somewhere in the of your page, and
Add $("#myDivId").html(results.response.title); in your success callback function
$.ajax({
url: "http://api.tumblr.com/v2/blog/myblog.tumblr.com/info?api_key=myapikey",
dataType: 'jsonp',
success: function(results){
// Logs to your javascript console.
console.log(results);
// writes the title to a div with the Id "myDivId" (ie. <div id="myDivId"></div>)
$("#myDivId").html(results.response.title);
}
});
In the question code, the request type was not being set and it was being rejected by tumblr. The jsonp error response was printing-out. The code below correctly makes the jsonp request.
The key was specifying the type, and the dataType. Good Luck happy hacking. ;-)
$.ajax({
type:'GET',
url: "http://api.tumblr.com/v2/blog/jdavidnet.tumblr.com/info",
dataType:'jsonp',
data: {
api_key : "myapikey"
},
success:function(response){
console.log(response, arguments);
}
});
One way to write an object to the screen is to add an element containing its JSON representation to the page:
$.ajax({
url: "http://api.tumblr.com/v2/blog/myblog.tumblr.com/info?api-key=myapikey",
dataType: 'jsonp',
success: function(results){
$("body").append(
$("<pre/>").text(JSON.stringify(results, null, " "))
);
}
});
Here is a demonstration: http://jsfiddle.net/MZR2Z/1/

jquery JSON node delete

I'm developing a web application with jax-rs, i made a rest client with jquery. I'm getting the result as json or xml, then showing them to html table. To facilitate table, im using JqGrid library. My problem is, for example Jqgrid wants to json object like below ;
[
{yaziNo:"1",yazar:"abc",yazi:"test",tarih:"2007-10-01"},
{yaziNo:"2",yazar:"cdfe",yazi:"test2",tarih:"2007-10-01"},
{yaziNo:"3",yazar:"cdfe",yazi:"test3",tarih:"2007-10-01"},
{yaziNo:"4",yazar:"abc",yazi:"test",tarih:"2007-10-01"},
{yaziNo:"5",yazar:"cdfe",yazi:"test2",tarih:"2007-10-01"},
{yaziNo:"6",yazar:"abc",yazi:"test3",tarih:"2007-10-01"},
{yaziNo:"7",yazar:"cdfe",yazi:"test",tarih:"2007-10-01"},
{yaziNo:"8",yazar:"abc",yazi:"test2",tarih:"2007-10-01"},
{yaziNo:"9",yazar:"abc",yazi:"test3",tarih:"2007-10-01"} ]
But, returned JSON from my rest server those like below;
{"yazi":
[{"tarih":"26.01.2012","yazar":"sdasdadsadasda","yazi":"gdfgdfgd","yaziNo":"1756"},
{"tarih":"26.01.2012","yazar":"sdasdadsadasda","yazi":"gdfgdfgd","yaziNo":"1755"},
{"tarih":"26.01.2012","yazar":"sdasdadsadasda","yazi":"gdfgdfgd","yaziNo":"1754"},
{"tarih":"26.01.2012","yazar":"sdasdadsadasda","yazi":"gdfgdfgd","yaziNo":"1753"},
{"tarih":"26.01.2012","yazar":"sdasdadsadasda","yazi":"gdfgdfgd","yaziNo":"1752"}]
}
How can i delete the "yazi" node but keeping inside.
edited:
jQuery("#list27").jqGrid({
url:'http://localhost:43842/KodcuComRESTful/kodcuRS/yazilar',
datatype: "json",
height: 255,
width: 700,
jsonReader: {root: "yazi", repeatitems: false},
colNames:['Yazi No','Yazar', 'Yazi', 'Tarih'],
colModel:[
{name:'yaziNo',index:'yaziNo', width:80, sorttype:"int"},
{name:'yazar',index:'yazar', width:180},
{name:'yazi',index:'yazi', width:370},
{name:'tarih',index:'tarih', width:100, align:"right",sortype:"date"}
],
rowNum:10,
rowTotal: 2000,
rowList : [20,30,50],
loadonce:true,
mtype: "GET",
rownumbers: true,
rownumWidth: 40,
gridview: true,
pager: '#pager27',
sortname: 'yaziNo',
viewrecords: true,
sortorder: "asc",
caption: "Loading data from server at once"
});
I see no problem with the data returned from the server. You should just use jsonReader option of jqGrid which informs jqGrid how to read the data from the server response. For example
jsonReader: {root: "yazi", repeatitems: false}
UPDATED: The demo uses the exact JSON data which you posted and it displays the results in the grid. I used the JavaScript code which you posted and replaced only height: 255 to height: "auto" to have more compact results.
The only problem which I see in your code is the usage of full URL: url:'http://localhost:43842/KodcuComRESTful/kodcuRS/yazilar'. Because of same origin policy restriction one can't get JSON data per Ajax from another source as the same site and port. So in case of usage datatype: "json" you should always use relative URL path like url:'/KodcuComRESTful/kodcuRS/yazilar' for example.

Solr live search using ExtJs4

i'm using solr+haystack(django plugin) on the backend and the search is working fine;
While Django(and Haystack) with its templates is doing everything for me(I mean its pretty simple to configure and use), ExtJS4 is a little more complex;
The question is how to use Solr using ExtJS4?
An example is very much appreciated;
Thanks for any help and sorry for my English;
As ExtJS4 is a MVC framework, the solution is done like MVC;
The controller/Search.js
Ext.define('yourapp.controller.Search',{
extend:'Ext.app.Controller',
stores:[
'Searches'
],
views:[
'search.Search',
'search.SearchList'
],
models:[
'Search'
],
init:function(){
this.control({
"search":{
'keyup':this.search,
},
});
},
search:function(inputedTxt, e, eOpts){
this.getSearchesStore().load({
//When sending a request, q will rely to request.POST['q'] on server-side;
//inputedTxt.getValue() -- a value, entered in textfield (or whatever)
params:{
q:inputedTxt.getValue()
},
callback:function(result){
if(result[0]){
//do something with the result
//i'd been creating a window with a grid inside. "Grid"'s view is written below.
}
}
}
});
The models/Search.js
Ext.define('yourapp.model.Search',{
extend:'Ext.data.Model',
fields:[
{name:'name', type:'string'}
]
});
The store/Searches.js
Ext.define('yourapp.store.Searches',{
extend:'Ext.data.Store',
storeId: "searchStore",
model:'yourapp.model.Search',
autoLoad: false,
proxy:{
type:'ajax',
// server-side url
url: '/searchlist/',
actionMethods:{create: "POST", read: "POST", update: "POST", destroy: "POST"},
reader:{
type:'json',
root:'searches'
}
}
});
The view/search/Search.js
//a Text field to input text;
Ext.define('yourapp.view.search.Search',{
extend:'Ext.form.field.Text',
alias: 'widget.search',
id: "searchView",
enableKeyEvents: true,
initComponent:function(){
this.callParent(arguments);
}
});
The view/search/SearchList.js
//a view for a result
Ext.define('yourapp.view.search.SearchList',{
extend: 'Ext.grid.Panel',
alias:'widget.searchlist',
title: 'search result',
store: 'Searches',
columns:[
{
header:'Name',
dataIndex:'name',
flex:1
}
]
});
Somewhere in the view/Viewport.js xtype: 'search', should be inserted for a text field to be displayed.
That's all for a ExtJS4 part.
On server-side -- Django:
'haystack' and Solr should be installed and configured (by 'configured' i mean: search should already work on the server-side);
In someapp/view.py
def searchlist(request):
from haystack.query import SearchQuerySet
# POST["q"] should be receivedt from our client-side
searchText = request.POST["q"]
sqs = SearchQuerySet().filter(name=searchText)
data = []
for result in sqs:
data.append({"name": result.object.name})
return HttpResponse('{ success:true, searches:'+simplejson.dumps(data)+'}', mimetype = 'application/json')
Finally in your urls.py you should add:
(r'^searchlist/','someapp.views.searchlist'),
That was for it. Best wishes.
P.S.
I know this is not the greatest answer and there's lack of explanation, but as for me, I rather prefer a code example than verbal explanation.
SOLR has JSON output from its queries using wt=json param and can readily be consumed by ExtJS.
http://wiki.apache.org/solr/SolJSON?action=fullsearch&context=180&value=jsonp&titlesearch=Titles#JSON_Response_Writer
if you need to use jsonp you can specify a callback function via this param json.wrf=callback

Why is my json encoded?

I have the following code which I post a bunch of JSON data to an ASHX file where I will process this data. Somehow the JSON is encoded and I have no clue what encoded it.
$.ajax({
url: '/save_objects_channels.ashx',
data: jsonParams,
contentType: 'application/json',
dataType: 'json',
success: function(data) {
},
error: function (xhr, ajaxOptions, thrownError){
},
complete: function() {
}
});
Here is my sample json that I posted (I generate this as string):
var jsonParams = '[ { objectID: 333, channelID: 3, supplierId: 2, checked: true },{ objectID: 444, channelID: 4, supplierId: 5, checked: true } ]';
jQuery encoded it. You chose to send it as a GET request (which is the default for .ajax()), which transfers all data in the URL as part of the query string. As Clement Herreman also points out, the query string must be encoded.
You might want to switch to type: "POST" in your .ajax() parameters.
GET requests have a length limit that can bite you when the JSON string gets longer. POST requests have virtually no size limit.
Plus, you will cause a data leak: Query strings are written to the web server logs, possibly sensitive data could end up there when you are not careful. POST requests are logged, too. But their payload will not be logged, as it is not part of the URL.
Because URL must be encoded, according the RFC 3986
Hint on how to encode url using Javascript : Encode URL in JavaScript?