ExtJS 4.2.1 - getters/setters using Associations not working - javascript

I'm having trouble trying to invoke getters/setters on a Model object that has an association with one other model. Here are the classes:
Category.js
Ext.define('Chapter05.model.Category', {
extend: 'Ext.data.Model',
fields: [
{ name: 'id', type: 'int' },
{ name: 'name', type: 'string' }
]
})
Product.js
Ext.define('Chapter05.model.Product', {
extend: 'Ext.data.Model',
requires: [
'Chapter05.model.Category'
],
fields: [
{ name: 'id', type: 'int' },
{ name: 'category_id', type: 'int' },
{ name: 'name', type: 'string' }
],
// we can use the belongsTo shortcut on the model to create a belongsTo association
associations: [
{ type: 'belongsTo', model: 'Chapter05.model.Category' }
]
})
Main.js
Ext.define('Chapter05.view.Main', {
extend: 'Ext.container.Container',
requires:[
'Ext.tab.Panel'
'Chapter05.model.Product',
'Chapter05.model.Category',
],
xtype: 'app-main',
layout: 'vbox',
items: [
{
xtype: 'button',
text: 'Category',
handler: function(evt) {
var product = new Chapter05.model.Product({
id: 100,
category_id: 20,
name: 'Sneakers'
});
product.getCategory(function(category, operation) {
// do something with the category object
alert(category.get('id')); // alerts 20
}, this);
}
}
]
});
The error occurs at the line where product.getCategory(...) is. I get the following message in Safari Web Inspector:
TypeError: 'undefined' is not a function (evaluating 'product.getCategory')
Am I forgetting to do something?
P.S.
The project(Chapter05) was generated using Sencha Cmd. Hence, the fully qualified names.

I've had a similar problem with a hasOne relation. It was solved by specifying the getters/setters and the associationKey yourself.
Something like:
belongsTo: {
model: 'Chapter05.model.Category',
getterName: 'getCategory',
setterName: 'setCategory',
associationKey: 'category_id'
}

Related

XTemplate definition on items property of a ListItem

I'm using Sencha 2.3.0 and I want to have a XTemplate side-to-side to a component (textfield) on a ListItem. The code above works fine for DataView/DataItem, but I want to use the grouped property that is only available on List/ListItem.
The nested Xtemplate gets rendered fine as DataItem. How can I make it work for ListItem? I'm also receptive for solutions that drop this nested structure and use the xtemplate as tpl property directly on the ListItem (of course the textfield with listeners must be implemented as well).
list
Ext.define( 'app.view.myList', {
//extend: 'Ext.dataview.DataView',
extend: 'Ext.dataview.List',
xtype: 'mylist',
requires: [
'app.view.MyItem'
],
config: {
title: "myTitle",
cls: 'mylist',
defaultType: 'myitem',
grouped: true,
store: 'myStore',
useComponents: true,
itemCls: 'myitem',
items: [
{
// some components
}
]
}
});
listitem
Ext.define( 'app.view.myItem', {
//extend: 'Ext.dataview.component.DataItem',
extend: 'Ext.dataview.component.ListItem',
xtype: 'myitem',
config: {
cls: 'myitem',
items: [
{
xtype: 'component',
tpl: new Ext.XTemplate([
'<table cellpadding="0" cellspacing="0" class="myitemXTemplate">',
//some xtemplate content
'</table>'
].join( "" ),
{
compiled: true
})
},
{
label: 'some label',
cls : 'myitemtextfield',
xtype: 'textfield',
name: 'myitemtextfield'
}
]
}
});
Thanks in advance!
Modifed /touch-2.4.2/examples/list/index.html
The model:
Ext.define('model1', {
extend: 'Ext.data.Model',
config: {
fields: [
{name: 'firstName', type: 'string'},
{name: 'lastName', type: 'string'}
]
}
});
The CustomListItem
Ext.define('DataItem', {
extend: 'Ext.dataview.component.ListItem',
xtype: 'basic-dataitem',
requires: [
'Ext.Button',
'Ext.Component',
'Ext.layout.HBox',
'Ext.field.Checkbox'
],
config: {
dataMap : {
/* getFirstname : {
setData : 'firstName'
},*/
getLastname : {
setValue : 'lastName'
}
},
layout: {
type: 'hbox',
height:'200px',
},
firstname: {
cls: 'firstname',
xtype:'component',
data:{data:'hej'},
tpl: new Ext.XTemplate([
'<H1>',
'{data}',
'</H1>'
].join(""),
{
compiled: true
})
},
lastname: {
xtype:'textfield',
css:'lastname'
}
},
applyFirstname : function (config) {
return Ext.factory(config, Ext.Component, this.getFirstname());
},
updateFirstname : function (newName) {
if (newName) {
this.add(newName);
}
},
applyLastname : function (config) {
return Ext.factory(config, Ext.Component, this.getLastname());
},
updateLastname : function (newAge) {
if (newAge) {
this.add(newAge);
}
},
applyFirstName: function (config) {
return Ext.factory(config, 'Ext.Component', this.getLastname());
},
updateRecord: function(record) {
if (!record) {
return;
}
this.getFirstname().setData({data:record.get("firstName")});
this.callParent(arguments);
}
});
The store
var store = Ext.create('Ext.data.Store', {
//give the store some fields
model: 'model1',
//filter the data using the firstName field
sorters: 'firstName',
//autoload the data from the server
autoLoad: true,
//setup the grouping functionality to group by the first letter of the firstName field
grouper: {
groupFn: function (record) {
return record.get('firstName')[0];
}
},
//setup the proxy for the store to use an ajax proxy and give it a url to load
//the local contacts.json file
proxy: {
type: 'ajax',
url: 'contacts.json'
}
});
The list
xtype: 'list',
useSimpleItems: false,
defaultType: 'basic-dataitem',
id: 'list',
ui: 'round',
//bind the store to this list
store: store

sencha touch: cant remove record from session storage

Cant delete a record from the store.
My model
Ext.define('touch.model.FilesModel', {
extend: 'Ext.data.Model',
requires: [
'Ext.data.identifier.Uuid'
],
config: {
identifier: 'uuid',
idProperty: 'iD',
fields: [
{ name: 'iD', type: 'auto' },
{ name: 'fileName', type: 'auto' }
]
}
});
and this is my SessionStorage
Ext.define('touch.store.FilesStore', {
extend: 'Ext.data.Store',
requires: [
'Ext.data.proxy.SessionStorage'
],
config: {
storeId: 'FilesStore',
autoLoad: true,
model: 'touch.model.FilesModel',
proxy: {
type: 'sessionstorage',
id: 'FilesStore-store-unique'
},
sorters: [{
property: 'created',
direction: 'DESC'
}]
}
});
I am trying to remove a record from the store, and it doesnt work.
i tried:
var filesStore = Ext.getStore('FilesStore');
filesStore.remove(filesStore.getAt(index)); // fails on this line: "Uncaught TypeError: Cannot read property 'destroy' of null" remove from the store
filesStore.sync();
then i tried just to do
var filesStore = Ext.getStore('FilesStore');
filesStore.getAt(index).erase() // fails with: [ERROR][Anonymous] You are trying to erase a model instance that doesn't have a Proxy specified

ExtJS5 MVVM local store

How to properly use MVVM viewmodel store?
List.js:
Ext.define('some.List', {
extend: 'Ext.tree.Panel',
requires: [
'some.ListModel'
],
rootVisible : false,
hideHeaders: true,
viewModel: {
type: 'list'
},
bind: {store:'{mlists}'},
columns: [{
xtype: 'treecolumn',
dataIndex: 'name',
flex: 1,
sortable: false,
}]
});
ListModel.js:
Ext.define('some.ListModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.list',
requires: [
'Ext.data.proxy.Ajax'
],
stores: {
mlists: {
autoLoad: true,
fields: [
{ name: 'id', type: 'int'},
{ name: 'name', type: 'string' },
{ name: 'count' },
{ name: 'group' }
],
proxy: {
type: 'ajax',
api: {
read: 'php/lists/read.php'
},
reader: {
type: 'json',
rootProperty: 'lists'
}
}
}
}
});
i get error:
Uncaught TypeError: undefined is not a function Panel.js?_dc=1404313037482:430
Ext.define.bindStore Panel.js?_dc=1404313037482:430
Ext.define.reconfigure Table.js?_dc=1404313037482:1417
Ext.define.setStore Table.js?_dc=1404313037482:1376
Ext.define.privates.onBindNotify Bindable.js?_dc=1404313037482:681
Ext.define.privates.notify BaseBinding.js?_dc=1404313037482:83
Ext.define.privates.react Binding.js?_dc=1404313037482:206
Ext.define.notify Scheduler.js?_dc=1404313037482:394
Ext.define.onTick Scheduler.js?_dc=1404313037482:425
(anonymous function) Function.js?_dc=1404313037482:121
There are several issues with the code:
If it is Sencha Cmd generated then view someList should be in view directory. Of course it would work when it is elsewhere but there must be a good reason not to follow Sencha recommended directory structure. This is not related to the issue.
Sencha recommends to start namespace with a capital letter to distinguish from other variables. It should read Some, not some in this case. It is not related to the issue.
someList extends TreePanel so it must use a TreeStore. mlists is normal store. It can be cause of the issue.
If you want to define a tree store in ViewModel, configure it with type:'tree' config option and do not forget to configure also root option that is mandatory for tree stores.
Then you can bind it normally as any other store the way you are already using.

Load JSON in Ext store, associations missing

I'm using Ext 4.1. I have some issues with loading json data with associations. The flat data gets loaded perfectly, only the 'hasMany' doesn't work. (if loaded there nowhere to be found). If a record is loaded I want to be able to get the 2 stores of Attendee's and the 1 store of documents.
I can also change the JSON format to a better format (if you have suggestions let me know!)
I have this json data.
This is my first model:
Ext.define('App.model.package.LabVisit', {
extend: 'Ext.data.Model',
requires: [
'App.model.package.Attendee',
'App.model.package.Document'
],
idProperty: 'labVisitID',
fields: [
{
mapping: 'lab_visit_id',
name: 'labVisitID',
type: 'int'
},
{
mapping: 'lab_id',
name: 'labID',
type: 'int'
},
... some more irrelevant...
{
mapping: 'comments',
name: 'comments'
},
{
name: 'upddate'
}
],
hasMany: [
/* edit: added foreignKey (also tried with: lab_visit_id) */
{ model: 'package.Attendee', name: 'attendeeLabList', associationKey:'attendee_lab', foreignKey: 'labVisitId' },
{ model: 'package.Attendee', name: 'attendeeEmpList', associationKey:'attendee_emp', foreignKey: 'labVisitId' }
{ model: 'package.Document', name: 'document', associationKey:'document' },
]
});
I have following attendee model:
Ext.define('App.model.package.Attendee', {
extend: 'Ext.data.Model',
fields: [
/* edit: added this field */
{
mapping: 'lab_visit_id',
name: 'labVisitId'
},
{
mapping: 'attendee_id',
name: 'AttendeeID'
},
{
mapping: 'first_name',
name: 'firstName'
},
{
mapping: 'last_name',
name: 'lastName'
},
{
name: 'email'
}
]
});
following document model:
Ext.define('App.model.package.Document', {
extend: 'Ext.data.Model',
fields: [
{
mapping: 'document_id',
name: 'docID'
},
{
mapping: 'document_name',
name: 'docName'
},
{
mapping: 'document_mimetype',
name: 'mimeType'
},
{
name: 'uploadID'
}
]
});
Finally my store:
Ext.define('App.store.package.LabVisit', {
extend: 'Ext.data.JsonStore',
requires: [
'App.model.package.LabVisit'
],
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.merge({
storeId: 'labVisitStore',
model: 'App.model.package.LabVisit',
remoteSort: true,
proxy: {
type: 'ajax',
api: {
read: API_URLS.getVisitList //url to the json
},
reader: {
type: 'json',
root: 'rows'
}
}
}, cfg)]);
}
});
Edit:
I've added the foreign key in the model and added it to the hasMany
Still no difference. This is my output:
I also find it a strange: If it's broken I expect an exception. And there are 2 mysterious stores always present but I don't have a clue why or what's the purpose.
The problem was in this part:
hasMany: [
{ model: 'package.Attendee', name: 'attendeeLabList', associationKey:'attendee_lab' },
{ model: 'package.Attendee', name: 'attendeeEmpList', associationKey:'attendee_emp' },
{ model: 'package.Document', name: 'document', associationKey:'document' },
]
#Izhaki helped me a lot. Thanx! Especially with the fiddle. I started there and begun with switching the code with my code piece by piece. Until I saw the model was the problem.
models should be defined like this: App.model.package.Attendee
I think it's sad that the framework doesn't show a significant error/warning if a model isn't recognised/doesn't excist/isn't supplied... But meh, it works now.

BelongsTo with ExtJS Model

I have two Models: "Identity" and "Profile". The identity 'belongsTo' profile. When I get a record of type 'identity', I want to (by this record) get the correspondent profile. I'm trying using the following code:
Ext.define('App.model.Identity', {
extend: 'Ext.data.Model',
fields: [
// ...
{name: 'id_profile', type: 'int'},
// ...
],
belongsTo: {
model: 'App.model.Profile',
primaryKey: 'id',
foreignKey: 'id_profile',
associatedName: 'Profile'
},
proxy: {
type: 'ajax',
api: {
read: App.Config.getBaseUrl() + '/admin_identity/list',
create: App.Config.getBaseUrl() + '/admin_identity/create',
update: App.Config.getBaseUrl() + '/admin_identity/update',
destroy: App.Config.getBaseUrl() + '/admin_identity/destroy'
},
reader: {
type: 'json',
root: 'data'
}
}
});
Ext.define('App.model.Profile', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
// ...
],
belongsTo: {
model: 'App.model.Identity',
primaryKey: 'id',
foreignKey: 'id_profile',
name: 'identities'
},
proxy: {
// ...
}
});
When I try to do this:
function viewProfile(identity) {
identity.getProfile(function(profile){
console.log(profile);
});
}
What I get is an empty profile's object. The strange thing is that the Identity class didn't do any http request to get the profile. I'm doing this right?
Thanks in advance
Have you tried:
identity.getProfile({
success:function(profile, operation){
},
failure: function(profile, operation){
//check for a failure
}
});
I would also try removing the associatedName property.

Categories