PDA

View Full Version : Using shared models for two apps



KJedi
23 Jan 2014, 3:08 PM
I have set up the sencha workspace and created two apps: frontend and backend. I also have a folder for common components. Here's what directory structure looks like:

/
.sencha
...
sencha.cfg
ext
build
frontend
app
...
app.js
backend
app
...
app.js
common
In backend/app.js I have:

Ext.Loader.setConfig({
enabled: true,
disableCaching: false,
paths: {
'CJ': '../common'
}
});
This should load all that starts from CJ.* from the common folder. It does so for the components, but for the models it doesn't work. I have a model in shared components, because it will be reused with associations. And I need the store for those models in the backend, because there is no collection of models on the frontend.
In order to make build work, I need different namespaces (otherwise build puts everything to the same folder).
So I create a store like this:

Ext.define('CJB.store.ApplicationStore', {
extend: 'Ext.data.Store',

requires: [
'CJ.model.Application'
],

constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
storeId: 'ApplicationStore',
model: 'Application'

}, cfg)]);
}
});
yes, I know it doesn't find proxy, but it does not matter for the case. Here's console output:

[W] CJB.store.ApplicationStore created with no model. The name 'Application' does not correspond to a valid model. ext-dev.js:12300
Uncaught TypeError: Cannot call method 'getProxy' of undefined AbstractStore.js:412
> CJ.model.Application (trying to see if it was loaded at all)
function constructor() { (yes, here it goes!)
// Opera has some problems returning from a constructor when Dragonfly isn't running. The || null seems to
// be sufficient to stop it misbehaving. Known to be required against 10.53, 11.51 and 11.61.
return this.constructor.apply(this, arguments) || null;
}

So Ext.Loader loads model (because I put it to requires:[]), but Store cannot use model from the different namespace.

How this can be solved? What is the right way to do this?

KJedi
23 Jan 2014, 4:29 PM
Guys, I found the solution. In case you need to do something similar, you need to reference model by full name AND require it in the store so it looks like this:

Ext.define('CJB.store.ApplicationStore', {
extend: 'Ext.data.Store',

requires: [
'Ext.data.proxy.Memory',
'Ext.data.reader.Json',
'Ext.data.Field',
'CJ.model.Application'
],

constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
storeId: 'ApplicationStore',
autoLoad: true,
model: 'CJ.model.Application',
...
And there is one more gotcha. When you use associations, you need to configure them in full form:

Ext.define('CJ.model.Application', {
extend: 'Ext.data.Model',
requires: 'CJ.model.Applicant',
fields: [....],
associations: [{
type: 'hasOne',
model: 'CJ.model.Applicant',
primaryKey: 'applicantId',
foreignKey: 'applicantId',
associationKey: 'applicant',
getterName: 'getApplicant'
}
1) You need to require model for association in the parent model
2) You need to reference model by full class name
3) You need to specify associationKey and getterName, otherwise they are generated from the full model name which is obviously not convenient when you have dots. You'll have getter like 'getCJ.Model.Applicant'. Still possible to call, but looks awful.

Hope it helps someone.
Please close the thread as answered.

Gary Schlosberg
24 Jan 2014, 1:47 PM
Glad to hear you found the solution, and thanks for taking the time to share it with the community.