Declaring model with belongsTo not generating getter - extjs

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: ...

Related

Using Ext.crete in Ext.define

Is it safe to use an Ext.create call in a Ext.define call ?
Example:
Ext.define('app.store.MyStore',{
extend: 'Ext.data.Store',
model: Ext.create('Ext.data.Model', {
idProperty: 'Id',
fields: [
{ name: 'Id', type: 'number' },
{ name: 'Name', type: 'number' }
]
}),
...
No, it is not. In fact with your code the model definition does not even get to the store. Try creating an instance of your store and check what fields the model of the store has:
const myStore = Ext.create('app.store.MyStore');
console.log(myStore.getModel().getFields());
The result will be an empty array. Now define your model and store like this:
Ext.define('app.store.MyModel', {
extend: 'Ext.data.Model',
idProperty: 'Id',
fields: [{
name: 'Id',
type: 'number'
}, {
name: 'Name',
type: 'number'
}]
});
Ext.define('app.store.MyStore', {
extend: 'Ext.data.Store',
model: 'app.store.MyModel'
});
Try the again to create a store and check for the model fields like above, now you will get an array with two elements, as expected.
Even if it were possible I would not recommend it. Chances are high that you will need this model definition somewhere else in you application.

Extjs hasOne association not loading preoperly

I have a Person model which has an Address associated to it via 'hasOne'. Both models load data via REST proxy. If I load a person and try to get the address I can see a http request to the url of the addresses but without any kind of person id in it so my server sends an error.
Person:
Ext.define('AP.model.Person', {
extend: 'Ext.data.Model',
fields: [
{ name: 'id', type: 'int', persist : false },
{ name: 'name', type: 'string' }
],
proxy: {
type: 'rest',
url : AP_ROOT_URL + 'persons/'
},
associations: [{
type: 'hasOne',
model: 'AP.model.Addresses',
foreignKey: 'person_id',
primaryKey: 'id',
getterName: "getAddress"
}]
});
Address:
Ext.define('AP.model.Address', {
extend: 'Ext.data.Model',
fields: [
{ name: 'person_id', type: 'int', persist : false },
{ name: 'address', type: 'string' }
],
proxy: {
type: 'rest',
url : AP_ROOT_URL + 'addresses/'
}
});
The following code:
person.getAddress(function(address){
console.log(address);
});
creates a request to:
http://localhost/addresses
when it should create a request to:
http://localhost/addresses/person_id (http://localhost/addresses/1)
What you have here is a HasMany relation, not HasOne. You won't get HasOne to work with these models because, as said in the docs: "the owner model is expected to have a foreign key which references the primary key of the associated model". In your case, the foreign key is in the associated model (which makes it a 1-n relationship).

Unable to insert in localstorage

I have model:
Ext.define('SizoMag.model.SizoBuscetModel', { extend: 'Ext.data.Model',
config: {
fields: [{name: 'text', type: 'string'}, {name: 'price', type: 'string'}],
proxy: {
type: 'localstorage',
id : 'buscetmodel'
}
}
});
and store
Ext.define('SizoMag.store.SizoBuscetStore', {extend: 'Ext.data.Store',
config: {
storeId: 'SizoBuscetStore'
}
});
But when I try to add an entry to the store - get error
[WARN][Ext.data.Operation#setModel] Unless you define your model using metadata, an Operation needs to have a model defined.Console.js:35
[WARN][Ext.data.reader.Reader#process] In order to read record data, a Reader needs to have a Model defined on it. Console.js:35
Uncaught TypeError: object is not a function
I add so
var store=Ext.getStore('SizoBuscetStore');
store.load();store.add({text:'txt',price:'150'});
store.sync();
Please help me/
Tnx
Try this instead, you need to define a model type for a store so it can configure its reader:
Ext.define('SizoMag.store.SizoBuscetStore', {
extend: 'Ext.data.Store',
storeId: 'SizoBuscetStore',
model: 'SizoBuscetModel'
});
Hey its Simple Try this
in Store:
Ext.define('e4b.store.Adult_DOBStore', {
extend: "Ext.data.Store",
config: {
model: "e4b.model.Adult_DOBModel",
autoLoad: true,
clearOnPageLoad: false,
}
});
and Your model will be
Ext.define('e4b.model.Adult_DOBModel', {
extend: 'Ext.data.Model',
config: {
fields: ['Adult1Date'],
proxy: {
type: 'localstorage',
id : 'adultdob'
}
}
});
And Now in your Contoller...
First Get the Value
var A_select1=Ext.getCmp('select1').getValue();
localStorage.setItem("Adult1_select1",A_select1); //Assign the value to localstore
var AdultSalutation={
// object
'Adult1_select1':A_select1,
};
var AdultSalutationstore =Ext.getStore('Adult_AdultSalutationstore');// cal store
AdultSalutationstore.add(AdultSalutation); // add the oject here
AdultSalutationstore.sync();
AdultSalutationstore.load();

EXTJS4--Why don't my associated stores load child data?

So I have a parent and child store, illustrated here:
Parent Model
Ext.define('APP.model.Client', {
extend: 'Ext.data.Model',
requires: [
'APP.model.Website', 'Ext.data.association.HasMany', 'Ext.data.association.BelongsTo'],
fields: [{
name: 'id',
type: 'string'
}, {
name: 'name',
type: 'string'
}, {
name: 'slug',
type: 'string'
}, {
name: 'active',
type: 'boolean'
}, {
name: 'current',
type: 'boolean'
}],
hasMany: {
model: 'APP.model.Website',
name: 'websites'
}
});
Child Model
Ext.define('APP.model.Website', {
extend: 'Ext.data.Model',
fields: [{
name: 'id',
type: 'string'
}, {
name: 'client_id',
type: 'string'
}, {
name: 'sub_domain',
type: 'string'
}, {
name: 'active',
type: 'boolean'
}],
belongsTo: 'APP.model.Client'
});
Using an AJAX call via the server, I am loading the Clients store, and that is loading fine. But the Websites store isn't populated, and when I breakpoint on the Clients store on.load function, to see what it's populated with, the Client store is only populated with the client data, but in the raw property for that store, I can see all the websites data. So it's being returned correctly, but my extjs isn't correct. Here are the stores:
Client Store
Ext.define('APP.store.Clients', {
extend: 'Ext.data.Store',
autoLoad: false,
model: 'APP.model.Client',
proxy: {
type: 'ajax',
url: '/client/list',
reader: {
type: 'json',
root: 'items'
}
},
sorters: [{
property: 'name',
direction: 'ASC'
}]
});
Websites Store
Ext.define('APP.store.Websites', {
extend: 'Ext.data.Store',
requires: ['Ext.ux.Msg'],
autoLoad: false,
model: 'APP.model.Website',
proxy: {
type: 'ajax',
url: '/client/list',
reader: {
type: 'json',
root: 'items'
},
writer: {
type: 'json'
}
},
sorters: [{
property: 'sub_domain',
direction: 'ASC'
}]
});
My final result is...I would like to populate both stores so I can click on an element, and when it loads something from the parent store, I can access the child store(s) (there will be more when I figure out this problem) to populate a couple grid(s) in tabs.
What am I missing as far as my setup? I just downloaded extjs4 a couple days ago, so I am on 4.1.
Put your proxies in your models, unless you have a good reason not to [1]
Make sure you require the related model(s), either in the same file, or earlier in the application
Use foreignKey if you want to load the related data at will (i.e. with a later network request).
Use associationKey if the related data is loaded in the same (nested) response
Or just use both
Always name your relationships (otherwise the name will be weird if using namespaces).
Always use the fully qualified model name for the model property in your relationships
Working code:
model/Contact.js:
Ext.define('Assoc.model.Contact', {
extend:'Ext.data.Model',
requires:[
'Assoc.model.PhoneNumber'
],
fields:[
'name' /* automatically has an 'id' field */
],
hasMany:[
{
model:'Assoc.model.PhoneNumber', /*use the fully-qualified name here*/
name:'phoneNumbers',
foreignKey:'contact_id',
associationKey:'phoneNumbers'
}
],
proxy:{
type:'ajax',
url:'assoc/data/contacts.json',
reader:{
type:'json',
root:'data'
}
}
});
model/PhoneNumber.js:
Ext.define('Assoc.model.PhoneNumber', {
extend:'Ext.data.Model',
fields:[
'number',
'contact_id'
],
proxy:{
type:'ajax',
url:'assoc/data/phone-numbers.json',
reader:{
type:'json',
root:'data'
}
}
});
data/contacts.json:
{
"data":[
{
"id":1,
"name":"neil",
"phoneNumbers":[
{
"id":999,
"contact_id":1,
"number":"9005551234"
}
]
}
]
}
data/phone-numbers.json
{
"data":[
{
"id":7,
"contact_id":1,
"number":"6045551212"
},
{
"id":88,
"contact_id":1,
"number":"8009996541"
},
]
}
app.js:
Ext.Loader.setConfig({
enabled:true
});
Ext.application({
requires:[
'Assoc.model.Contact'
],
name:'Assoc',
appFolder:'Assoc',
launch:function(){
/* load child models that are in the response (uses associationKey): */
Assoc.model.Contact.load(1, {
success: function(record){
console.log(record.phoneNumbers());
}
});
/* load child models at will (uses foreignKey). this overwrites child model that are in the first load response */
Assoc.model.Contact.load(1, {
success: function(record){
record.phoneNumbers().load({
callback:function(){
console.log(arguments);
}
});
}
});
}
});
[1] A store will use its model's proxy. You can always override the store's proxy if need be. You won't be able to use Model.load() if the model has no proxy.
Your assumption is wrong. You expect that the WebSite store loads itself but that is not how it works. What you can do is the following (this is untested but is how I do it in all my projects):
In your clients grid add a listener for the itemclick event to call the following method (showWebSites). It will receive the selected client record containing the selected APP.model.Client instance. Then, and given that each client has a set of WebSites, the method will load the APP.store.Websites store and the client´s websites will be displayed in your view.
showWebSites: function (sender, selectedClient) {
Ext.StoreManager.lookup('APP.store.Websites')
.loadData(selectedClient.data.WebSites);
}
This is the way. I hope you find it useful.

Including a data Store makes the app not load

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.

Resources