Hi everyone!
I'm trying to get dojox.grid working in a CakePHP project and I'm a little bit frustrated, so if anyone knows how to do it... please help!!
I've been able to load data from my cake model into the dojo store with the cake JSON component (at least that's what Firebug says!), but I can't pass it to the grid. I don't know how to debug further. Any ideas?
I'm a dojo newbe, so please be patient... Thanks a lot in advance!
Kchopein.

Some more info:
Here's the json generated by Cake:
{"timestamp":1193692111, "items":[ {"Post":{"id":"1","title":"The title","body":"This is the post body.","created":"2007-11-07 00:44:54"}}, {"Post":{"id":"2","title":"A title once again","body":"And the post body follows.","created":"2007-11-07 00:45:15"}}, {"Post":{"id":"3","title":"Title strikes back","body":"This is really exciting! Not.","created":"2007-11-07 00:45:44"}}, {"Post":{"id":"4","title":"aaaaaa","body":"aaaaaadadasdas","created":"2007-11-12 10:00:45"}} ]}Here's my code:
/* tundraGrid.css matches Dijit Tundra style. Others forthcoming. Use Grid.css on the same path for a more color-neutral theme */ @import "http://localhost/dojo/dojox/grid/_grid/tundraGrid.css"; dojo.require("dojo.data.ItemFileReadStore"); dojo.require("dojox.grid.Grid"); dojo.require("dojox.grid._data.model"); dojo.require("dojo.parser"); //Definiendo la vista de la rejilla: var view = { cells: [[ {name: 'Id', field: 'id'}, {name: 'Title', field: 'title'}, {name: 'Body', field: 'body'}, {name: 'Creation date', field: 'created'}, ]] }; var layout = [view];The result: a grid with the head titles, but no data in it.
Any of you, wise men (and women), can help this poor apprentice?
Thanks a lot!
One of the Grid requirements
Thanks for providing the code for review.
One of the Grid requirements is that it or its container have a defined size, preferably in units, not %.
Try something like:
<div id="grid" dojoType="dojox.Grid" model="model" structure="layout" style="width:100px;height:50px"></div>Didn't work :-(
Hi frankf!
I've tried what you suggested but no success. I get the same result: I can see the grid widget, but no data in it. When it loads displays a "?" under each column header, but it disappears at the end, so I think that the problem is in the data or (I bet on this one) my layout. Anyway I don't know how to solve it and it's very frustrating...
I can access the items with with some code, but not the grid.
Thanks a lot anyway!!
P.D: You are the one who's helping me, so I give you thanks. The least I can do is give all the information I have!! ;-)
Change your query from
Change your query from "items" to "id". [I missed it at first... :-)]
Good try but...
didn't work :-P.
Thanks a lot anyway!!
ItemFileReadStore doesn't like inner objects
In the example data you sent every item seems to have one attribute/property "Post" that's an object containing the actual data. This way not only the field-pointers in your view are incorrect, but it also seems to break stuff in ItemFileReadStore. I'd recommend you to check if you can configure CakePHP json-serializer to format the data without this "Post"-level - see:
{"id":"1","title":"The title","body":"This is ...","created":"2007-11-07 00:44:54"},
{"id":"2","title":"A title once again","body":"And ...","created":"2007-11-07 00:45:15"}
]}
Mmmm, sounds good!
I'll try it tomorrow (it's night here!) and give feedback, but sounds logical to me.
Thanks a lot for your help!!
No success...
Hi Maine!
I've tried what you said without success. Anyway I still think that what I was doing was wrong,, but there must be something more. Using Firebug to see what's happening I've noticed that the model object is empty, without any trace of the "posts". Is this normal or there's something wrong?
Thanks a lot in advance!
Done at last!!
Hi!! Finally I've done, thanks to all of you!!
-frackf was right with the "query" issue: it was "id" instead "intem" and...
-Maine was right with the "object level" issue. I don't know why it doesn't work when I paste your code in my editor, but...
-hydra12 (from the CahePHP Google Group) showed me how to get that structure with cake and it worked!!
Thanks a lot to all of you!!
Missing Identifier?
Um, it occurred to me that there's still identifier missing! Try this:
"timestamp":1193692111,
"items":[
{"id":"1","title":"The title","body":"This is ...","created":"2007-11-07 00:44:54"},
{"id":"2","title":"A title once again","body":"And ...","created":"2007-11-07 00:45:15"}
]
}
CakePHP Read Store.
Hi!
Important update: This store is unnecessary to have the grid working with CakePHP since you can use the dojox.data.QueryReadStore with the setting requestMode="post" and get the values. Sorry, I'm new to cake too :-(
Reading the this thread about sorting and paging in dojo.data (very useful for the grid) and working a little bit I made this cake.data.CakeReadStore witch combined with the xyz.data.ServerGridData (here) might be useful for people trying to get the grid working with CakePHP:
if(!dojo._hasResource["cake.data.CakeReadStore"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. dojo._hasResource["cake.data.CakeReadStore"] = true; dojo.provide("cake.data.CakeReadStore"); dojo.provide("cake.data.CakeReadStore.InvalidItemError"); dojo.provide("cake.data.CakeReadStore.InvalidAttributeError"); dojo.require("dojo.string"); dojo.require("dojo.data.util.simpleFetch"); dojo.require("dojox.data.QueryReadStore"); dojo.declare("cake.data.CakeReadStore", dojox.data.QueryReadStore, { /* // summary: // This class provides a store that is mainly intended to be used // for loading data dynamically from the server, used i.e. for // retreiving chunks of data from huge data stores on the server (by server-side filtering!). // Upon calling the fetch() method of this store the data are requested from // the server if they are not yet loaded for paging (or cached). // // For example used for a combobox which works on lots of data. It // can be used to retreive the data partially upon entering the // letters "ac" it returns only items like "action", "acting", etc. // // note: // The field name "id" in a query is reserved for looking up data // by id. This is necessary as before the first fetch, the store // has no way of knowing which field the server will declare as // identifier. // // examples: // // The parameter "query" contains the data that are sent to the server. // var store = new cake.data.CakeReadStore({url:'/search.php'}); // store.fetch({query:{name:'a'}, queryOptions:{ignoreCase:false}}); // // // Since "serverQuery" is given, it overrules and those data are // // sent to the server. // var store = new dojox.data.QueryReadStore({url:'/search.php'}); // store.fetch({serverQuery:{name:'a'}, queryOptions:{ignoreCase:false}}); // // todo: // - there is a bug in the paging, when i set start:2, count:5 after an initial fetch() and doClientPaging:true // it returns 6 elemetns, though count=5, try it in QueryReadStore.html // - allow configuring if the paging shall takes place on the client or the server // - add optional caching // - when the first query searched for "a" and the next for a subset of // the first, i.e. "ab" then we actually dont need a server request, if // we have client paging, we just need to filter the items we already have // that might also be tooo much logic */ //So we can rebuild the query por pagination. _baseurl:"", requestMethod:"post", //useCache:false, // We use the name in the errors, once the name is fixed hardcode it, may be. _className:"cake.data.CakeReadStore", // If this is false, every request is sent to the server. // If it's true a second request with the same query will not issue another // request, but use the already returned data. This assumes that the server // does not do the paging. doClientPaging:false, constructor: function(/* Object */ params){ dojo.mixin(this,params); this._baseurl = this.url; }, fetch:function(/* Object? */ request){ // summary: // See dojo.data.util.simpleFetch.fetch() this is just a copy and I adjusted // only the paging, since it happens on the server if doClientPaging is // false, thx to http://trac.dojotoolkit.org/ticket/4761 reporting this. // Would be nice to be able to use simpleFetch() to reduce copied code, // but i dont know how yet. Ideas please! request = request || {}; if(!request.store){ request.store = this; } var self = this; var _errorHandler = function(errorData, requestObject){ if(requestObject.onError){ var scope = requestObject.scope || dojo.global; requestObject.onError.call(scope, errorData, requestObject); } }; var _fetchHandler = function(items, requestObject){ var oldAbortFunction = requestObject.abort || null; var aborted = false; var startIndex = requestObject.start?requestObject.start:0; if (self.doClientPaging==false) { // For client paging we dont need no slicing of the result. startIndex = 0; } var endIndex = requestObject.count?(startIndex + requestObject.count):items.length; requestObject.abort = function(){ aborted = true; if(oldAbortFunction){ oldAbortFunction.call(requestObject); } }; var scope = requestObject.scope || dojo.global; if(!requestObject.store){ requestObject.store = self; } if(requestObject.onBegin){ requestObject.onBegin.call(scope, items.length, requestObject); } if(requestObject.sort){ items.sort(dojo.data.util.sorter.createSortFunction(requestObject.sort, self)); } if(requestObject.onItem){ for(var i = startIndex; (i < items.length) && (i < endIndex); ++i){ var item = items[i]; if(!aborted){ requestObject.onItem.call(scope, item, requestObject); } } } if(requestObject.onComplete && !aborted){ var subset = null; if (!requestObject.onItem) { subset = items.slice(startIndex, endIndex); } requestObject.onComplete.call(scope, subset, requestObject); } }; request.store.url = request.store.url + "/" + request.start + "/" + request.count + "/" + request.serverQuery.sort; this._fetchItems(request, _fetchHandler, _errorHandler); this.url = this._baseurl; return request; // Object }, getLabelAttributes: function(/* item */ item){ return null; }, }); dojo.declare("cake.data.CakeReadStore.InvalidItemError", Error, {}); dojo.declare("cake.data.CakeReadStore.InvalidAttributeError", Error, {}); }If someone has any idea to improve it, please share!!
Errors in Errors
Thanks for sharing! We still don't have that many samples here in dojotoolkit.org. However, I wanted prevent two Errors - see: QueryReadStore: declared error classes broken (InvalidItemError, InvalidAttributeError) (All the bugs for QueryReadStore).
Ok, thanks!!
Thanks again Maine!!
I've deleted those 2 lines at the end of the class. Still learning (very fast, I must say) thanks to you.
How about the Model, getRowCount in particular?
Just out of curiosity, what kind of model did you use? If it's similar to the ones on the paging and sorting thread, it's maybe not worth of repeating, but otherwise it'd be nice to see that, so maybe eventually we can arrive to some "best practices". One method here that I'm interested in particular is getRowCount - see Problematic getRowCount. I feel that we still lack an elegant asynchronous solution. Or maybe we need an architectural change, so that we got rid of the whole method?
Model from the paging and sorting thread.
Hi Maine!
I'm using the xyz.data.ServerGridData model from the paging and sorting thread that you mention. I have the same problem with the getRowCount, and I'm thinking in the best way to solve it. I think that it would be nice if the store had a method to do that, so the model could ask for it. As far as I understand the store is the one that deals with the server, so I think it should do this too. What do you think?
Note I'm new to dojo, so please be patient if I'm saying weird things :-) Hey, trying to help!