PDA

View Full Version : Stores and Models



dombroskib
18 Jun 2010, 8:02 AM
Trying to play with the kiva sample and convert it to use a regular store with a JsonReader backing it (reusing the back end from extjs development). I can't get it to work as I get an error that the model is undefined in ext-touch-debug line 11505.


Ext.regModel('CheckModel', {
fields: [
{name:'APAmount'},
{name:'Provider'},
{name:'ARAmount'},
{name:'ProfitAmt'},
{name:'ProfitPercent'},
{name:'State'},
{name:'City'},
{name:'Claimant'},
{name:'Payer'},
{name:'ApptDate'},
{name:'ApptType'},
{name:'Department'},
{name:'Speciality'}
]
});


this.store = new Ext.data.Store({
id: 'edc-store-checks',
storeId: 'edc-check-store',
url: '/MessageHub.aspx',
model: 'CheckModel',
reader: new Ext.data.JsonReader({
root: 'Items',
totalProperty: 'Count',
id: 'openitems',
model: 'CheckModel'

})
});



Tried stepping thru the code (learning experience on doing that in Safari) and don't ever see a key being added to the underlying mixedcollection of the ModelMgr. Am I missing something (.90 version of touch).

elmasse
18 Jun 2010, 8:53 AM
Got the same issue, I just modified the code, try this:

Not a nice solution, but it is working for me. The main issue is automatically registering writers and readers since they are created automatically and no root, model and so on are attached :(



Ext.data.JsonReader.override({
buildExtractors : function() {
if (typeof this.model == 'string') {
this.model = Ext.ModelMgr.types[this.model];
}
Ext.data.JsonReader.superclass.buildExtractors.apply(this, arguments);

if (this.root) {
this.getRoot = this.createAccessor(this.root);
} else {
this.getRoot = function(root) {
return root;
};
}
}
});

Ext.data.JsonStore = Ext.extend(Ext.data.Store, {
/**
* @cfg {Ext.data.DataReader} reader @hide
*/
constructor: function(config){
if(config && config.url){
config.proxy = new Ext.data.AjaxProxy(config);
}
Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(config, {
reader: new Ext.data.JsonReader(config)
}));
}
});
Ext.reg('jsonstore', Ext.data.JsonStore);

dombroskib
18 Jun 2010, 9:08 AM
That seemed to do the trick, thank you! Don't seem to get the load listener to work either. Did you have issues with it?

dombroskib
18 Jun 2010, 9:31 AM
Now read the docs, event is no longer there.

edspencer
18 Jun 2010, 10:45 AM
In Sencha Touch the data package was rearchitected such that Stores have Proxies, which in turn contain their Readers and Writers, like this:



this.store = new Ext.data.Store({
id: 'edc-store-checks',
storeId: 'edc-check-store',
url: '/MessageHub.aspx',
model: 'CheckModel',
proxy: {
type: 'ajax',
reader: {
type: 'json',
root: 'Items',
totalProperty: 'Count'
}
}
});


Defining a Reader directly on a Store is not currently supported. Thanks for pointing this out though as our docs on this are currently out of date.

dombroskib
19 Jun 2010, 3:52 AM
Thanks Ed. Spending more time in the touch code I realise that all though I am tempted to apply all of Ext JS techniques I need to be wary that touch currently supports it. Appreciate the efforts, so far I am happy with where this is headed

jay@moduscreate.com
19 Jun 2010, 12:03 PM
In Sencha Touch the data package was rearchitected such that Stores have Proxies, which in turn contain their Readers and Writers, like this:



this.store = new Ext.data.Store({
id: 'edc-store-checks',
storeId: 'edc-check-store',
url: '/MessageHub.aspx',
model: 'CheckModel',
proxy: {
type: 'ajax',
reader: {
type: 'json',
root: 'Items',
totalProperty: 'Count'
}
}
});


Defining a Reader directly on a Store is not currently supported. Thanks for pointing this out though as our docs on this are currently out of date.
That is f'ing sexy! Total abstraction, and really makes configuration extremely easy.

I really hope this makes it in to 4.0

edspencer
19 Jun 2010, 1:31 PM
That is f'ing sexy! Total abstraction, and really makes configuration extremely easy.

I really hope this makes it in to 4.0

Sencha Touch's data package is the 4.0 data package - they are identical. There's a lot more to come too :)

epalm
8 Jul 2010, 11:13 AM
In Sencha Touch the data package was rearchitected such that Stores have Proxies, which in turn contain their Readers and Writers, like this:



this.store = new Ext.data.Store({
id: 'edc-store-checks',
storeId: 'edc-check-store',
url: '/MessageHub.aspx',
model: 'CheckModel',
proxy: {
type: 'ajax',
reader: {
type: 'json',
root: 'Items',
totalProperty: 'Count'
}
}
});



This gives me "url is undefined"

edspencer
8 Jul 2010, 2:42 PM
Put the url on the Proxy instead of the Store. The Proxy abstracts away the CRUD mechanism that the Store relies on, so a Store can switch between a LocalStorageProxy and an AjaxProxy and rely on the same interface. The url is therefore meaningful to the Proxy, not the Store.

This was a design change from the current Ext JS 3.x architecture, we're preparing documentation to guide developers through the usage of the data package.

aiwilliams
23 Dec 2010, 2:15 PM
I've run into an issue with this documentation: http://dev.sencha.com/deploy/touch/docs/?class=Ext.data.Model See the section, "Usage in Stores". Notice how it is implied that the Store will now use the proxy configured on the registered model? It isn't working. I am seeing this error: "Error: You are using a ServerProxy but have not supplied it with a url.". Here is the code:


Ext.regModel('QuestionType', {
fields: ['label', 'identifier'],
proxy : {
type: 'rest',
url : '/api/admin/v1/questions/types'
}
});

var store = new Ext.data.JsonStore({
model: 'QuestionType',
autoLoad: true
});

Am I misunderstanding this, or done something wrong? It would seem that this is a good approach, so that, should the Model be used in other Stores, we don't have to configure new proxies to the same server interface.

aiwilliams
23 Dec 2010, 2:50 PM
After stepping through the code, I've discovered that the problem is the use of the JsonStore - it sets a proxy in it's options, which means that the one on the model is not used in the super constructor! So, I've switched to using the non-JsonStore, Store. Now I'm getting a problem in the RestProxy#buildUrl method. "Result of expression 'request.operation.records' [undefined] is not an object.". Does the RestProxy not understand the autoLoad procedure?! I'm going to try a different proxy, but man...

aiwilliams
23 Dec 2010, 3:02 PM
Models can be configured with a Proxy - those are used to get instances from the server. The Proxy is used by a Store - those are used by DataViews to show and do stuff to the Model instances.

Sencha Touch provides a RestProxy to make CRUD easy.
Sencha Touch provides a JsonStore to make reading JSON data easy.

The RestProxy cannot load a collection, as it depends on working with a single record at a time, anytime it attempts to buildUrl. I had to use it's superclass, AjaxProxy.

The JsonStore prevents the use of the Model's configured proxy by assuming in it's constructor that it should create a new AjaxProxy configure to read/write JSON!

aiwilliams
6 Jan 2011, 12:36 PM
So, as you may know, 1.0.1a fixes this issue - the RestProxy works for reading collections. Now it fails to write when configured with a format parameter.

See how the format is appended to the url, so you end up with '/users/.json'?


buildUrl: function(request) {
var records = request.operation.records || [],
record = records[0],
format = this.format,
url = request.url || this.url;

if (this.appendId && record) {
if (!url.match(/\/$/)) {
url += '/';
}

url += record.getId();
}

if (format) {
if (!url.match(/\.$/)) {
url += '.';
}

url += format;
}

request.url = url;

return Ext.data.RestProxy.superclass.buildUrl.apply(this, arguments);
}

aiwilliams
6 Jan 2011, 12:44 PM
A diff that fixes it, but I don't have any tests to run:



--- a/sencha-touch-debug.js
+++ b/sencha-touch-debug.js
@@ -8764,7 +8764,7 @@ Ext.data.RestProxy = Ext.extend(Ext.data.AjaxProxy, {
format = this.format,
url = request.url || this.url;

- if (this.appendId && record) {
+ if (this.appendId && record && record.getId()) {
if (!url.match(/\/$/)) {
url += '/';
}
@@ -8772,7 +8772,7 @@ Ext.data.RestProxy = Ext.extend(Ext.data.AjaxProxy, {
url += record.getId();
}

- if (format) {
+ if (format && request.action == 'read') {
if (!url.match(/\.$/)) {
url += '.';
}