jqgrid with JSON input rendering empty - django

I'm trying to generate a jqgrid which populates from a JSON feed, being output from a django backend.
The python handling the request is as follows:
from django.http import HttpResponse
from django.utils import simplejson
def json_test(request):
results = {'total':'1',
'page':'1',
'records':'2',
'rows':[{'id':'1','field1':'blah','field2':'bleh'},
{'id':'2','field1':'bloo','field2':'blum'}]}
json = simplejson.dumps(results)
return HttpResponse(json, mimetype='application/json')
So going to http://127.0.0.1:8000/json_test/ returns the following:
{"records": "2", "total": "1", "rows": [{"field2": "bleh", "field1": "blah", "id": "1"}, {"field2": "blum", "field1": "bloo", "id": "2"}], "page": "1"}
The jquery code is as follows:
<script type="text/javascript">
jQuery(document).ready(function(){
jQuery("#list").jqGrid({
url:'http://127.0.0.1:8000/json_test/',
datatype: 'json',
mtype: 'GET',
colNames:['field1','field2'],
colModel :[
{name:'field1', width:55},
{name:'field2', width:90},
],
pager: '#pager',
rowNum:10,
rowList:[10,20],
sortname: 'field1',
sortorder: 'desc',
viewrecords: true,
caption: 'Test Grid'
});
});
</script>
On loading the page, the grid renders correctly, and it briefly displays 'loading data', but it then displays no rows.
Any ideas where I've gone wrong? I've tried to strip this back to as simple a case as possible to determine the cause.

According to the jqGrid Documentation, by default the grid expects JSON data in the following format:
{
total: "xxx",
page: "yyy",
records: "zzz",
rows : [
{id:"1", cell:["cell11", "cell12", "cell13"]},
{id:"2", cell:["cell21", "cell22", "cell23"]},
...
]
}
So basically it looks like you need to set an ID for each of your columns. If this is not feasible you would need to specify your own jsonReader.
Additionally, having your total/page/records sections out-of-order might cause problems - if you still have trouble after adding the ID's then this would be the next thing to look at.

Solved - I put the html page inside the django app, so that the jqgrid url became just url:'/json_test/' and then it worked. Must be something harcoded into jqgrid that only permits local urls?

try this...
loadError: function(xhr,status,error){alert(status+" "+error);}

Related

ObjectAt(0) doesn't work with Ember.Controller

I'm trying to upgrade my Ember application to the latest Ember 1.13.2 and therefore am trying to replace all Ember.ArrayController with Ember.Controller.
I've got a problem with the category-controller of my blog. The data retrieved from my server looks like this:
"posts": [
{
"category": {
"id": "1",
"name": "tech"}
"title": "my title",
"body": "post-content",
"isPublished": true,
},
...
]
In my category-controller I need both, the category-id and the category-name.
With the Ember.ArrayController I used objectAt(0) to get both from the first post loaded in the model for that purpose but this doesn't work with Ember.Controller anymore.
How can I get these two attributes in my controller?
This code doesn't work anymore:
breadCrumb: function(){
return this.objectAt(0).get('category').get('name');
}.property('model.[]'),
categoryId: function(){
return this.objectAt(0).get('category').get('id');
}.property('model.[]'),
You just get it from the model directly instead of using the proxy behavior:
return this.get('model').objectAt(0).get('category').get('name');
Or, if you like shorthand:
return this.get('model.firstObject.category.name');
EDIT: While I'm at it, you could also declare these as aliases:
breadCrumb: Ember.computed.alias('model.firstObject.category.name'),
If you don't do that, you should probably change your dependent key. Your property won't update if the nested properties change. You need to use something like model.firstObject.category.name or model.#each.category.name.

How to Model.fetch(<object>) when the returned data is a single object

I want to make an API call for searching that looks like this:
https://myapi.com/search/<query>/<token>
where query is the search term and token (optional) is an alphanumeric set of characters which identifies the position of my latest batch of results, which is used for infinite scrolling.
This call returns the following JSON response:
{
"meta": { ... },
"results" {
"token": "125fwegg3t32",
"content": [
{
"id": "125125122778",
"text": "Lorem ipsum...",
...
},
{
"id": "125125122778",
"text": "Dolor sit amet...",
...
},
...
]
}
}
content is an array of (embedded) items that I'm displaying as search results. My models look like this:
App.Content = Em.Model.extend({
id: Em.attr(),
text: Em.attr(),
...
});
App.Results = Em.Model.extend({
token: Em.attr(),
content: Em.hasMany('App.Content', {
key: 'content',
embedded: true
})
});
In order to make that API call, I figured I have to do something like this:
App.Results.reopenClass({
adapter: Em.RESTAdapter.create({
findQuery: function(klass, records, params) {
var self = this,
url = this.buildURL(klass) + '/' + params.query;
if (params.token) {
url += '/' + params.token;
}
return this.ajax(url).then(function(data) {
self.didFindQuery(klass, records, params, data);
return records;
});
}
}),
url: 'https://myapi.com/search',
});
then somewhere in my routes do this:
App.Results.fetch({query: 'query', token: '12kgkj398512j'}).then(function(data) {
// do something
return data;
})
but because the API returns a single object and Em.RESTAdapter.findQuery expects an array, an error occurs when Ember Model tries to materialize the data. So how do I do this properly? I'm using the latest build of Ember Model.
By the way, I'm aware that it would be much more convenient if the API was designed in a way so I can just call App.Content.fetch(<object>), which would return a similar JSON response, but I would then be able to set the collectionKey option to content and my data would be properly materialized.
You simply need to override your models load() method to adjust the payload hash to what Ember.Model wants. There are no serializers in Ember.Model. There is both a class level load for handling collections and an instance level load for loading the JSON specific to a single model. You want to override the instance level load method to wrap the content key value in an array if its not one already.
I have been using Ember.Mode quite heavily and enhanced it for a number of my use cases and submitted PR's for both fixes and enhancements. Those PRs have been sitting there for a while with no response from the maintainers. I have now moved to Ember.Data which has been 'rebooted' so to speak and having a lot better result with it now.
I would strongly suggest walking away from Ember.Model as it appears dead with the new pragmatic direction Ember Data has taken and because the project maintainer doesn't appear to have any interest in it anymore.

Ember Data serialize relationship without parent ID

I'm building an adapter to wrap the Keen.io API, so far I've been able to successfully load the projects resource, however the returned object looks like this:
{
partners_url: "/3.0/projects/<ID>/partners",
name: "Project Name",
url: "/3.0/projects/<ID>",
saved_queries: [ ],
events_url: "/3.0/projects/<ID>/events",
id: "<ID>",
organization_id: "<ORG ID>",
queries_url: "/3.0/projects/<ID>/queries",
api_key: "<API KEY>",
events: [
{
url: "/3.0/projects/<ID>/events/user_signup",
name: "user_signup"
},
{
url: "/3.0/projects/<ID>/events/user_converted",
name: "user_converted"
},
{
url: "/3.0/projects/<ID>/events/user_created_project",
name: "user_created_project"
}
]
}
Excluding a lot of cruft, Ember has no trouble mapping the name and id attributes using the RESTSerializer, but if I add an events relation to my Project model it blows up with:
Error while loading route: TypeError: Cannot set property 'store' of undefined
at Ember.Object.extend.modelFor (http://localhost:3000/assets/ember-data.js?body=1:9813:23)
at Ember.Object.extend.recordForId (http://localhost:3000/assets/ember-data.js?body=1:9266:21)
at deserializeRecordId (http://localhost:3000/assets/ember-data.js?body=1:10197:27)
at deserializeRecordIds (http://localhost:3000/assets/ember-data.js?body=1:10211:9)
at http://localhost:3000/assets/ember-data.js?body=1:10177:11
at http://localhost:3000/assets/ember-data.js?body=1:8518:20
at http://localhost:3000/assets/ember.js?body=1:3404:16
at Object.OrderedSet.forEach (http://localhost:3000/assets/ember.js?body=1:3247:10)
at Object.Map.forEach (http://localhost:3000/assets/ember.js?body=1:3402:10)
at Function.Model.reopenClass.eachRelationship (http://localhost:3000/assets/ember-data.js?body=1:8517:42)
From my investigation this seems to be because it can't find the inverse relation to map an Event back to a Project because there's no parent ID.
Is it possible to create a relation in Ember Data to support this? Or is it possible to modify the Serializer to append a projectId to each event before loading?
I'm using Ember 1.5.0-beta.4 and Ember Data 1.0.0-beta.7+canary.f482da04.
Assuming your Project model is setup the following way:
App.Project = DS.Model.extend({
events: DS.hasMany('event');
});
You need to make sure that the JSON from your API is in a certain shape that Ember-Data expects.
{
"project": {
"id": 1,
"events": ["1", "2"],
},
"events": [{
"id": "1",
"name": "foo"
}, {
"id": "2",
"name": "bar"
}]
}
You can, however, implement extractArrayin your model's serializer to transform the JSON from the server into something similar like the above example.
There's a working example and an explanation in the Ember docs.

Should marionette backbone model fields be automatically available for templates

I have a collection calling a remote REST server and getting back a JSON object containing fields including arrays. My Model is being called on each iteration through the collection, and I can get one of the fields to render in my template. Here's where things get strange...
If I do the following in the template:
<%= name %>
I can get the name field to output. However, any other fields will not render, unless I create some defaults at the beginning of the Model thus:
defaults: {
name: '',
phone: '',
age: ''
}
So, if I include this, I can render those fields. Should I have to do that on a model to use it's fields?
... as requested by n8eil
Template:
<script type="text/template" id="pos-list-item">
<%= name %>, <%= description %>, <%= cost %>
</script>
JSON Object:
{
"itemCount": 3,
"items": [
{
"uri": "/item/1234",
"name": "Soda Drink",
"description": "A fizzy drink",
"price": [
{
"costType": "A",
"cost": 3.5
}
],
"live": true,
"created": "2013-10-07 18:22:29"
},
{
"uri": "/item/12345",
"name": "Choco bar",
"description": "A nice snack",
"price": [
{
"costType": "B"
"cost": 1.75
}
],
"live": true,
"created": "2013-10-07 18:22:29"
}
]
}
Changed some data for project privacy but this is essentially the layout of the JSON object. I need 'name', 'description' and 'cost' to appear in the template as above. I can log 'price' out to the console and it shows as an object but I cannot single out the 'cost' field...
http://jsbin.com/eHoPAri/1/edit?html,js,console,output
I went ahead and mocked up some Marionette structures for this data, not sure if they're close to what you're doing. The only thing I needed to change for the template was that 'cost' is inside an object inside the 'price' array, so you need to reference it by 'price[0].cost'. Otherwise no, you should not need default properties on a model in order for them to be rendered in the template, but you will get an error if you try to reference a property not found on the model.
You could also put in a method to add a 'cost' property to the model when it's loaded so you don't have to reference it from the array :
var itemModel = Backbone.Model.extend({
parse : function(response, options){
return _.extend(response, { 'cost' : response['price'][0]['cost'] })
}
});
Hope this helps
Yes, the field would have to exist when rendering that template. However, you could modify the template and not have to include defaults:
<%= name ? name : '' %>

How do I output a JSON object with underscore.js?

I am using the underscore.js template library with my backbone example. My template looks like this:
<script id="results-template" type="text/template">
<h2><%= title %></h2>
</script>
The JSON object looks like this:
{"src":"placeholder.jpg","title":"an image placeholder","coordinates":[0,0],"tags":["untagged"],"location":"home"}
I am trying to parse this object through my template but the error I get through my console is:
Uncaught ReferenceError: title is not defined
What am I doing wrong? Live fiddle is here: http://jsfiddle.net/amit_e/muLjV/46/
your problem is this:
JSON.stringify(myPhoto)
this needs to be
myPhoto.toJSON()
reason: your JSON.stringify() will put the whole myPhoto model as a json string. now, Backbone has this function to output json as a json object, so you can use model.toJSON()
updated jsfiddle: http://jsfiddle.net/saelfaer/muLjV/50/
If you want to display only title, it is not required to process whole JSON of Photo model. You can just retrieve the single property.
Below Render will suffice the need here.
render: function(event){
var yourOutput={title:myPhoto.get('title')};
var compiled_template = _.template( $("#results-template").html(),yourOutput);
this.el.html(compiled_template);
}
Your current JSON object is as below. It is not much complex, you can get any of title, src,coordinates,tags, location without effort.
{
"src": "placeholder.jpg",
"title": "an image placeholder",
"coordinates": [0,0],
"tags": ["untagged"],
"location": "home"
}