I'm relatively new to ExtJS and I'm having trouble with what I believe is a core concept. In my application I'd like to define a model, create an instance and load it. I've looked high and low for an example that works on the web, but am stumped.
Everytime I try to load the model, the load function doesn't look to exist. The error I get in the console is "TypeError: timezoneDetails.load is not a function".
Here is the code I an using to try and illustrate this:
Ext.define('App.model.Model', {
extend: 'Ext.data.Model',
idProperty: 'ID',
proxy: {
type: 'rest',
url: '/timezones'
},
fields: [{
name: 'BaseUtcOffset',
type: 'string'
}, {
name: 'DisplayName',
type: 'string'
}, {
name: 'DisplayName',
type: 'string'
}, {
name: 'ID',
type: 'string'
}, {
name: 'SupportsDaylightSavingTime',
type: 'boolean'
}],
});
Ext.application({
name: 'App',
appFolder: 'app',
launch: function() {
var timezoneDetails = Ext.create('App.model.Model', {
ID: 'Bob'
});
timezoneDetails.load(); // TypeError: timezoneDetails.load is not a function
}
});
A Sencha Fiddle of this code is available here: https://fiddle.sencha.com/#fiddle/1lq
load is static on each model class. You'll get the record in the callback.
App.model.Model.load(1, function(rec) {
console.log(rec.getId());
});
Related
I have 2 models... a Parent and a Child... a Parent hasMany Child models. In the Child, I have a field that is created by using its data (in this example, it's just converting and returning 1). In the Parent, I have two conversions going on... one uses its data, and the 2nd one depends on the Child's data. However, when creating the Parent model, it appears the Child association isn't fully baked yet, but when I go to update the Parent model with a new value, the Child association is there.
Basically, what I want to know is, when you see the Total2 console firing, I want Test to be populated. How do I force the associations to be read before using my conversion functions in the parent? And ideally, if there's a change in the Child, the dependent conversion function in Parent will automatically fire... I realize that most likely won't be possible, but it would be an incredible added bonus.
Here's my example.
app.js
Ext.application({
name : 'Fiddle',
launch : function() {
var store = Ext.create('Ext.data.Store', {
model: 'Namespace.model.Parent',
autoLoad: true,
listeners: {
load: onLoadStore
}
});
var grid = Ext.create('Ext.grid.Panel', {
title: 'associations',
store: store,
renderTo: Ext.getBody(),
columns: [{
text: 'Primary Key',
dataIndex: 'PrimaryKey'
}]
});
function onLoadStore(store, records, successful, eOpts) {
var firstGroups = store.first().getGroupsStore();
console.log('before', firstGroups.getCount(), firstGroups.isLoaded());
firstGroups.first().set('GroupName', 'blah');
store.first().set('blank', 1)
}
}
});
Parent
Ext.define('Namespace.model.Parent', {
extend: 'Ext.data.Model',
alias: 'model.parent',
requires: [
'Ext.data.field.Integer',
'Ext.data.field.String',
'Namespace.model.Child'
],
idProperty: "PrimaryKey",
fields: [{
type: 'string',
name: 'PrimaryKey',
critical: true
}, {
type: 'string',
name: 'Title'
}, {
type: 'int',
name: 'Rating',
defaultValue: 2
}, {
type: 'int',
name: 'Total',
depends: ['Rating'],
convert: function(value, record) {
console.log('Total', record)
return record.get('Rating') * 2;
}
}, {
name: 'Total2',
type: 'int',
depends: ['groupsMapping', 'blank'],
// depends on child's Test property
convert: function(value, record) {
var groupsMapping = record.get('groupsMapping');
if (groupsMapping) {
for (var i = 0; i < groupsMapping.length; i++) {
console.log('Total2', groupsMapping[i].GroupName, groupsMapping[i].Test);
}
}
return 0;
}
}, {
name: 'groupsMapping',
type: 'auto',
mapping: 'Groups'
}, {
name: 'blank',
type: 'int'
}],
hasMany: [{
model: 'Namespace.model.Child',
associationKey: 'Groups',
name: 'getGroupsStore'
}],
proxy: {
type: 'ajax',
url: 'data1.json'
}
});
Child
Ext.define('Namespace.model.Child', {
extend: 'Ext.data.Model',
alias: 'model.child',
fields: [{
type: 'int',
name: 'GroupInt',
critical: true
}, {
type: 'string',
name: 'GroupName'
}, {
name: 'Test',
type: 'int',
depends: ['GroupName'],
convert: function() {
console.log('Test, parent depends on this')
return 1;
}
}],
proxy: {
type: 'memory'
}
});
I've hit the same problem and took me some time in order to realise that the associations are not available on conversion time
Like in your example, I was sending the child records together with the parent ones (nested) and have 'manually' built a fake store using child model & parent field child data in order to do my math for the conversion / calculation, which did the trick:
{
name: 'validationScore',
depends: ['childRecords'],
type: 'number',
persist: false,
convertOnSet: true,
convert: function(val, rec){
// here we have access only to direct record field, and not the association association !
// we can use data directly in the calculation
children = rec.get('childRecords');
// or build a fake store in order to easily parse them
children = Ext.create('Ext.data.Store', {
model: 'Namespace.model.ChildModel',
data: rec.get('childRecords')
})
// ... calculate whatever
return result;
}
}
But now my 'new' challenge is to figure it out a (good) solution to update the converted value upon child records' changes ...
I did something similar to qdev, except I listened on the actual association's store. There's something funky about the constructor though... if I didn't put that timeout in there, then I would get an error with trying to access the first record in the store load... might be a framework bug, or I'm doing something terrible. The important code is the constructor and calculate method... in the app, I just have a 1 second timeout on changing the child data... you can see the grid's row data change from 3 to 102. Here's an updated example:
constructor: function(config) {
this.callParent(arguments);
var me = this;
setTimeout(function() {
var groupsStore = me.getGroupsStore();
if (groupsStore) {
groupsStore.on('update', me.calculateChanges, me);
groupsStore.on('datachanged', me.calculateChanges, me);
}
me.calculateChanges();
}, 1);
},
calculateChanges: function() {
console.log('calculating');
var groupsStore = this.getGroupsStore();
if (groupsStore) {
var total2 = 0;
groupsStore.each(function(group) {
total2 += group.get('Test');
});
this.set('Total2', total2);
}
},
I am trying to filter in a combobox under Sencha Touch framework but I am not loading correct the records in the list.
My code is:
onTemplatesFilterChoosen: function(field, newValue, oldValue){
var store = Ext.getStore('Customers'),
templatesStore = store.getAt(0).templates(), //get the associated store
text = field.getRecord().data.text;
templatesStore.clearFilter();
//here the code to filter main store based in records of the associated store
}
But it is not working correctly and my store.getCount()for example is 0, showing a empty list.
In my main model I am adding a new model based in the properties of the filter called "CustomerTemplateModel"
associations: [
{
type: 'hasMany',
associatedModel: 'x.customer.model.CustomerTemplateModel',
ownerModel: 'x.customer.model.CustomerModel',
associationKey: 'templates',
autoLoad: true,
filterProperty: 'value',
name: 'templates'
}
]
And here the model associated:
Ext.define('x.customer.model.CustomerTemplateModel', {
extend: 'Ext.data.Model',
requires:[
],
config: {
useCache: false,
rootProperty: 'templates',
fields: [
{
name: 'text',
type: 'string'
},
{
name: 'value',
type: 'string'
}
]
}
});
What am I doing wrong??
Thank you in advance.
I have defined a model type that represent an object with xtype 'image'. Now i'm trying to load this objects in Ext.Panel from JSON using ComponentLoader:
Ext.define('ItemModel', {
extend: 'Ext.data.Model',
idProperty: 'itemModel',
fields: [{
name: 'id',
type: 'int'
},{
name: 'xtype',
type: 'string'
},{
name: 'src',
type: 'string'
}]
});
var previews = Ext.create('Ext.Panel',{
layout: 'column',
height: 500,
items: {
loader:{
autoLoad : true,
url: 'php/read.php',
renderer: "component"
}
}
});
But i get such error:
TypeError: me.el is null
me.container = Ext.get(me.el.dom.parentNode);
JSON which returned by read.php looks just like this:
{"items":[{"id":0,"xtype":"image","src":"img\/newalbum.png"},{"id":1,"xtype":"image","src":"img\/newalbum1.png"}]}
But if i'm create a 'store' with 'reader', and trying iterate loaded objects, it's works fine:
Ext.define('ItemModel', {
extend: 'Ext.data.Model',
idProperty: 'itemModel',
fields: [{
name: 'id',
type: 'int'
},{
name: 'xtype',
type: 'string'
},{
name: 'src',
type: 'string'
}]
});
Ext.define('ItemModelStore', {
extend: 'Ext.data.Store',
model: 'ItemModel',
proxy: {
type: 'ajax',
url: 'php/read.php',
reader: {
type: 'json',
root: 'items'
}
}
});
var itemModelStore = Ext.create('ItemModelStore');
itemModelStore.load(function() {
itemModelStore.each(function(record){
alert(record.get('src'));
});
});
I have created a tree panel in ExtJs 4.1 and that panel is associated with store. I have some JSON data available in a variable. How can I load that into into tree store on click of a button.
Ext.define('User', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
{name: 'name', type: 'string'},
{name: 'phone', type: 'string', mapping: 'phoneNumber'}
]
});
var data = {
users: [
{
id: 1,
name: 'Ed Spencer',
phoneNumber: '555 1234'
},
{
id: 2,
name: 'Abe Elias',
phoneNumber: '666 1234'
}
]
};
//note how we set the 'root' in the reader to match the data structure above
var store = Ext.create('Ext.data.TreeStore', {
autoLoad: false,
model: 'User',
proxy: {
type: 'memory',
}
});
How can I load data on click of a button?
var store = Ext.create('Ext.data.TreeStore', {
model: yourModel, // make sure the model fits
proxy: {
data : yourData, // this is your var with json
type: 'memory',
reader: {
type: 'json'
}
},
});
Check out the answers over here: Load static data to Ext.data.TreeStore
To run your code on a button click, do:
Ext.create('Ext.Button', {
text: 'Click me',
handler: function() {
// load the store
}
});
Try store.data = data, It appears that there is no methods like 'setData', just try store.data = data maybe it will work
you can use store.loadData method on buttons click. Check doc here.
I have inherited an ExtJs4 project, and I've got a fairly basic question.
I have a view that has a newly added checkbox field as one of the items, like so:
{
boxLabel: 'Test Message?',
xtype: 'checkboxfield',
id: 'cbTextMessage',
checked: false,
name: 'testMessage',
inputValue: true,
uncheckedValue: false
}
When the record is active, this value changes to the appropriate checked or unchecked state. When creating a new record, the value is set to the value of the checkbox. However, when editing an existing record, the model never gets updated to any value other than the original value.
The model:
Ext.define('PushAdmin.model.Message', {
extend: 'Ext.data.Model',
idProperty: 'id',
requires: ['Proxy.ParameterProxy'],
fields: [
{ name: 'id', type: 'int' },
{ name: 'games', type: 'auto',
convert: function(data, model) {
data = ( data && !Ext.isArray(data) ) ? [data] : data;
return data;
}
},
{ name: 'msgEnglish', type: 'string' },
{ name: 'msgFrench', type: 'string' },
{ name: 'msgSpanish', type: 'string' },
{ name: 'testMessage', type: 'bool' },
{ name: 'sendAt', type: 'date' },
{ name: 'note', type: 'string'},
{ name: 'status', type: 'string' },
],
proxy: {
type: 'rest',
url: '/apnsadmin/rest/Message',
pageParam: undefined,
startParam: undefined,
limitParam: undefined,
reader: {
type: 'json',
root: 'data',
successProperty: 'success'
}
}
});
And finally this is the function that gets called when the save button is clicked.
click: function () {
var grid = this.getQueuedMessagesGrid();
var sm = grid.getSelectionModel();
var selectedRecord = sm.getCount() > 0 ? sm.getSelection()[0] : undefined;
this.getMessageForm().getForm().updateRecord();
var newRecord = this.getMessageForm().getForm().getRecord();
if (selectedRecord!=undefined) {
console.log(selectedRecord);
console.log(newRecord);
selectedRecord.save();
} else {
// New record!
console.log("Saving new record");
grid.getStore().add(newRecord);
newRecord.save();
}
this.getMessageForm().setDisabled(true);
this.getMessageForm().getForm().reset();
}
},
I am aware that things are probably not the proper ExtJS way to do things, but since this is mostly working I am trying not to have to rewrite large chunks of it. I'd just like to know what I'm doing wrong in adding this checkbox/boolean field to the form.