Including a data Store makes the app not load - extjs

I can't get my application to work using MVC architecture.
Here is the code:
app.js
Ext.application({
name: CONFIG.APP_NS,
appFolder: '../js/app',
autoCreateViewport: true,
/*
models: ['User'],
stores: ['Users'],
//*/
controllers: ['Main', 'Tab', 'Import', 'Export', 'Predict', 'Admin']
});
Import.js (controller)
Ext.define(CONFIG.APP_NS+'.controller.Import', {
extend: 'Ext.app.Controller',
//stores: ['Users'], //Uncommenting this makes the application not load at all
models: ['User'],
views: ['Import.Window', 'Import.Toolbar', 'Import.Grid'],
init: function(){
...
},
...
});
User.js (model)
Ext.define(CONFIG.APP_NS+'.model.User', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
{name: 'username', type: 'string'},
{name: 'password', type: 'string'},
{name: 'salt', type: 'string'},
{name: 'firstName', type: 'string'},
{name: 'lastName', type: 'string'},
{name: 'email', type: 'string'},
{name: 'admin', type: 'boolean'},
{name: 'authenticated', type: 'boolean'}
],
hasMany: {model: CONFIG.APP_NS+'.model.Roles', name: 'roles'},
proxy: {
type: 'ajax',
url: 'model/users',
reader: {
type: 'json'
}
}
});
Ext.define(CONFIG.APP_NS+'.model.Roles', {
extend: 'Ext.data.Model',
fields: [
{name: 'role', type: 'string'}
],
belongsTo: CONFIG.APP_NS+'.model.User'
});
Users.js (store)
Ext.define(CONFIG.APP_NS+'store.Users', {
extend: 'Ext.data.Store',
requires: CONFIG.APP_NS+'.model.User',
model: CONFIG.APP_NS+'.model.User'
});
Grid.js (view)
Ext.define(CONFIG.APP_NS+'.view.Import.Grid', {
extend: 'Ext.grid.Panel',
alias: 'widget.importgrid',
initComponent: function() {
this.store = Ext.create('Ext.data.Store', { //Works fine with the code as it is
model: CONFIG.APP_NS+'.model.User',
proxy: {
type: 'ajax',
url: 'model/users',
reader: {
type: 'json'
}
}
});
//*/
//this.store = Ext.create(CONFIG.APP_NS+'.store.Users', {});
this.columns = [
{header: 'Name', dataIndex: 'username', flex: 1},
{header: 'Email', dataIndex: 'email', flex: 1}
];
this.callParent(arguments);
this.store.load();
}
});
I have tried almost every combination of stores: in different files possible, nothing seems to do the trick. If I do not include the store anywhere, I get the error Object is not a function (or TypeError: Cannot call method 'on' of undefined if defined outside of the initComponent in the view) somewhere in internal extjs files. It seems that even if I copy the structure from the tutorial examples, it still does not work, so I must be missing something.
What am I doing wrong?
Thank you for your time.
EDITS:
I am running this code on Wamp (localhost). The server has both ExtJS4 and Symfony installed and running.
Updated error message.
Fixed a typo in the Model, see comments.

(I see you have the stores commented out in the app.js. Is this intentional?)
I ran into a similar problem.. as soon as i added the store to my app.js and view.js (a grid panel), my app stopped working.
I'm pretty sure I fixed it by adding the stores (all of them) to the controller and the app.js. Ok.. just checked again, and I get a different error message if the store was missing from controller.js: "Uncaught TypeError: Cannot call method 'on' of undefined" (this is on chrome). Slightly different error message.
Also, consider commenting out the this.store.load().. i.e. remove the server data-access variable - (one thing at a time.)

I found the bug.
Users.js (store)
Ext.define(CONFIG.APP_NS+'store.Users', {
extend: 'Ext.data.Store',
requires: CONFIG.APP_NS+'.model.User',
model: CONFIG.APP_NS+'.model.User'
});
First line should be:
Ext.define(CONFIG.APP_NS+'.store.Users', {
I was missing a period before store.
Molecule Man's comment made me recheck all the definitions, thank you.

Related

ExtJS localstorage proxy model/store issue

I'm using ExtJS 5.1.0 and running into a strange problem.
I have the following model:
Ext.define('cardioCatalogQT.model.Load', {
extend: 'Ext.data.Model',
config:{
idProperty: 'id',
fields: [
{name: 'key', type: 'string'},
{name: 'comparator', type: 'string'},
{name: 'value', type: 'string'},
{name: 'type', type: 'string'}
]
}
});
And the Store:
Ext.define('cardioCatalogQT.store.Payload', {
extend: 'Ext.data.Store',
alias: 'store.Payload',
// add package.framework=ext to .sencha/app/sencha.cfg
config:{
model: 'cardioCatalogQT.model.Load',
storeId: 'Payload',
autoLoad: true,
proxy: {
type: 'localstorage'
}
}
});
When I add a record to the store:
var payload = Ext.create('cardioCatalogQT.store.Payload');
payload.add({
type: 'dx',
key: item.data.code,
comparator: 'eq',
value: item.data.description
});
payload.sync();
The data in localstorage look like all the records except for #7 and #11 in the attached image
However, when I add the field elements to the store like this:
Ext.define('cardioCatalogQT.store.Payload', {
extend: 'Ext.data.Store',
alias: 'store.Payload',
// add package.framework=ext to .sencha/app/sencha.cfg
config:{
idProperty: 'id',
fields: [
{name: 'type', type: 'string'},
{name: 'key', type: 'string'},
{name: 'comparator', type: 'string'},
{name: 'value', type: 'string'}
] ,
//model: 'cardioCatalogQT.model.Load',
storeId: 'Payload',
autoLoad: true,
proxy: {
type: 'localstorage'
}
}
});
I get the desired results in 7 and 11.
One other issue, is instead of giving an actual name to the model record, I get the very not useful name of ext-data-proxy-localstorage-N for the model instance.
Also, I am getting this error when referencing the model via the store:
[Error] Failed to load resource: the server responded with a status of 404 (Not Found) (cardioCatalogQT.model.Load, line 0)
I have done a sencha app build and no errors were thrown.
Any idea as to what I am doing wrong (I am basically doing what I've done with Sencha Touch, where I had much success)? Is this a bug, perhaps?
Issue was for ExtJS, to get the desired name on the store, you have to specify and id in the proxy:
proxy: {
type: 'localstorage',
id : 'payload'
}
Now, the model instances in my localstorage are showing up as desired, and I can query them using standard methods, like findRecord. Good times!
Moral of the story: ExtJS has different behaviors than Touch

Extjs two instances of stores not using different models

edit http://jsfiddle.net/zns6B/4/ Added js fiddle link and running into a cannot get 'Fields' of undefined now
edit2 So i found that the second grids store model is correct with Sc.Model.B. But the records in the store have ids that are Sc.Model.A . So my store model is set to Sc.Model.B but the store is using Sc.Model.A . It still gets stores the data in the store but only as if the model was set to Sc.Model.A in the first place.
edit3 I have take all the creation of instance out of my ListGrid. I have instead added them when creating the list grid. I have added the following. This does not work either. I am at a lose for what to do.
var obj1 = Ext.create('Sc.ListGrid',{
title: "first Component",
foo: true,
id: 'firstGrid',
myStore: Ext.create('My.Store.MyStore',{model:Ext.create('My.Model.Model'});
renderTo: 'renderToMe1'
});
I am trying to generate these two grids. When foo == true i want it to generate a store with model A. When it equals false i want it to use model B. I have tried to just specifically add the My.Model.MyModel but that does not work. The second grid will somehow inherit the first models model. I have changed it just to try and use fields instead of using the model at all but the second grid still uses the first grids.
I have also tried declaring the Stores inside the initComponent as well but i get the same result either way.
var obj1 = Ext.create('Sc.ListGrid',{
title: "first Component",
foo: true,
id: 'firstGrid',
renderTo: 'renderToMe1'
});
var obj2 = Ext.create('Sc.ListGrid',{
title: "second Component",
foo: false,
renderTo: 'renderToMe2'
});
Sc.ListGrid
Ext.define('Sc.ListGrid', {
extend: 'Ext.grid.Panel',
title: 'Grid',
store: Ext.data.StoreManager.lookup('bleh'),
requires: ['stuff'],
columns: [
{ text: 'id', dataIndex: 'id' },
],
config:{
foo: null,
},
initComponent: function(){
if(this.foo == true){
Ext.apply(this,{
store: this.buildStore1()
});
}
if(this.foo == false){
Ext.apply(this,{
store: this.buildStore2()
});
}
this.callParent();
},
buildStore1:function(){
return Ext.create('Sc.Store.League.LeagueStore',{url:'somewhere',fields:["S"]});
},
buildStore2:function(){
return Ext.create('Sc.Store.League.LeagueStore',{url:'somewhere',fields:["A"]});
}
});
Also an example of a model i am trying to use as well.
Ext.define('Sc.Model.A', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'string'},
{name: 'type', type: 'string'},
{name: 'gamename', type: 'string'}
]
});
Ext.define('Sc.Model.B', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'string'},
{name: 'type', type: 'string'},
{name: 'gamename', type: 'string'},
{name: 'something1', type: 'string'},
{name: 'something2', type: 'string'},
]
});
It will create both grids and load the data from my webservice. When i check the grid with Sc.Model.B's data it will have id and type. But will not have any data for something1, and something2. My webserivce is returning json and all values are entered. There are no nulls. If i Ext.getCmp('firstGrid').getStore().getData(0); If i use Ext.getCmp('firstGrid').getStore() and check the model name. It shows Model B but reflects A
Do you need it to be done in the initComponent()??
This is a fiddle I saved from a while ago when I was trying to do something similar. If you need help tweaking it let me know and ill update it.
The main thing to note is the grid.reconfigure(store,columns);
That will change the grid's store and columns appropriately.
http://jsfiddle.net/zqG55/1/
The issue was that the proxy wasn't being set or created properly because the proxy model was referencing the previous model instance. This is my solution
var themodel = 'A.Model.SomeModel';
var myProxy = new Ext.data.proxy.Ajax({
model: themodel,
url: url,
reader: {
type: 'json',
}
});
Ext.apply(this,{
columns: modelColumns.columns,
store: Ext.create('M.Store.MyStore',{
model: themodel ,
autoLoad: true,
proxy: myProxy
})
});

Declaring model with belongsTo not generating getter

Based on some examples of Ext.data.Model with associations I wrote the following class:
Ext.define('MyApp.model.Children',{
extend: 'Ext.data.Model',
fields : [{
name: 'parent' //object of the belongsTo
},{
name: 'description',
type: 'string'
}],
belongsTo : [{
name: 'parent',
foreignKey: 'parent', //also tried parent.id
instanceName: 'parent',
getterName: 'getParent',
model: 'MyApp.model.Parent'
}],
proxy : {
type: 'rest',
url: '../rest/children',
reader : {
type: 'json',
root: 'data'
}
}
});
Shouldn't this definition generate a getChildren method? The MyApp.model.Parent also have a proxy defined.
I'm testing with:
var store = Ext.create('Ext.data.Store',{
model: 'MyApp.model.Children'
});
store.load(function(recs){
console.log(recs[0].getParent); //prints undefined instead of function
});
It looks like your parent model isn't loaded. Try adding the requires configuration to your child model.
Ext.define('MyApp.model.Children', {
extend: 'Ext.data.Model',
//ensures the Parent model is loaded first
requires: 'MyApp.model.Parent',
fields: ...

Is there a way to define model fields in function?

The normal way to define a model is as follows:
Ext.define('App.MyModel', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
{name: 'name', type: 'string'}
]
});
Is there a way to specify the fields (and perhaps all the config properties) inside an init-type method, similar to how a component's config can be set in initComponent()?
It would be useful to have this capability in order to do things like set local vars for certain repetitive properties.
You can define a function anywhere you want in Javascript!
Ext.define('App.MyModel', {
extend: 'Ext.data.Model',
fields: function() {
return [
{name: 'id', type: 'int'},
{name: 'name', type: 'string'}
];
}() // important: run it immediately!
});
You could also do something like this in initComponent. I use this sometimes when creating stores within a component passing in a variable based on whether or not I want the store to autoLoad.
Ext.define('App.MyModel', {
extend: 'Ext.data.Model',
initFields: function(fieldType) {
return [
{name: 'id', type: fieldType},
{name: 'name', type: fieldType}
];
},
initComponent: function() {
var me = this;
Ext.apply(me, {
fields: me.initFields('string')
});
me.callParent();
}
});

Where's my EXT JS 4 model data?

Using Ext JS 4.1....
I have a grid that displays a bunch of Model instances, although only some of the fields are displayed. I then have a double-click listener where I would like to load the entire record into a form for editing. In the double-click listener I do not see the data in my hasMany association although the json data is being returned according to Firebug's Net display where I see the response from the server call. Is there something wrong with my model or am I going about this wrong?
Request.js
Ext.define('Request', {
extend: 'Ext.data.Model',
requires: ['PointOfContact'],
fields: [
{name: 'id', type: 'int'},
{name: 'project', type: 'string'},
{name: 'purpose', type: 'string'},
{name: 'status'},
{name: 'additionalInfo', type: 'string'}
],
hasMany: [{
model: 'PointOfContact',
name: 'pointOfContacts',
foreignKey: 'id',
associationKey: 'pointOfContacts'
}],
proxy: {
type: 'rest',
url: '/web/project/rest/request/',
reader: { type: 'json' },
writer: { type: 'json' }
}
});
PointOfContact.js
Ext.define('PointOfContact', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
{name: 'fullName', type: 'string'},
{name: 'email', type: 'string'},
{name: 'phone', type: 'string'}
]
});
Requests.js
Ext.define('Requests', {
extend: 'Ext.data.Store',
model: 'Request',
autoLoad: true
});
RequestsView.js
Ext.define('RequestsView', {
extend: 'Ext.grid.Panel',
title: 'All Requests',
store: 'Requests',
viewConfig: {
singleSelect: 'true',
listeners: {
itemdblclick: function(dataview, record, item, index, e) {
console.log(record.get('project'));
console.log(record.get('purpose'));
console.log(record.get('status'));
console.log(record.get('additionalInfo'));
console.log(record.get('pointOfContacts'));
var comp = Ext.ComponentQuery.query('requestForm');
comp[0].getForm().loadRecord(record);
var mainPanel = Ext.ComponentQuery.query('mainpanel');
mainPanel[0].getLayout().setActiveItem('requestForm');
}
}
},
columns: [
{header: 'Project', dataIndex: 'project', flex: 1},
{header: 'Purpose', dataIndex: 'purpose', flex: 1},
{header: 'Status', dataIndex: 'status', flex: 1}
]
});
So in the console I see the values for project, purpose, status and additionalInfo but I get "undefined" for pointOfContacts.
Any suggestions?
UPDATE WITH FINAL WORKING CODE:
Here is the working code I used to retrieve the pointofContacts and load a grid on my form panel with the pointOfContacts
...
itemdblclick: function(dataview, record, item, e) {
var comp = Ext.ComponentQuery.query('requestForm');
comp[0].getForm().loadRecord(record);
Ext.getCmp('pocGrid').reconfigure(record.pointOfContacts());
var mainPanel = Ext.ComponentQuery.query('mainpanel');
mainPanel[0].getLayout().setActiveItem('requestForm');
}
....
Has many associations are not parsed in to associated records by default. Especially for the grid - as that is supposed to be a flat data view. Model docs show you how to setup associations but don't say anything about creating instances for you :)
There are links to usage of has many (http://docs.sencha.com/ext-js/4-1/#!/api/Ext.data.association.HasMany) from the Model docs. Unfortunately the usage is not what you expect it to be. Essentially it is designed to fetch the records on demand by calling their store to load.

Resources