Using Ext.crete in Ext.define - extjs

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.

Related

Trying to use JSONStore in a combo

In our application we have a lot of name/value stores, and they are created at load time and put into a JSONStore like so :
Ext.create("Ext.data.JsonStore", {
data: data,
model: 'EM.model.controlUnit.CodeList',
storeId: "cl_" + tableId,
sorters: [{
sorterFn: aSorterFunction
}],
});
The model is pretty simple and looks like this :
Ext.define('EM.model.controlUnit.CodeList', {
extend: 'Ext.data.Model',
fields: [{
name: 'value', type: 'int'
}, {
name: 'label', type: 'string'
}, {
name: 'description', type: 'string'
}]
});
I thought stores were pretty interchangeable so I decided to use the store in the combo (There is no special combo store so I thought a JSONStore must be as good as a SimpleStore). I get the store like so :
var msDataStore = Ext.getStore("cl_t_cl_maritalstatus");
And use the store like so :
{
xtype: 'combo',
fieldLabel: 'Marital Status',
displayField: "label",
valueField: "value",
store: msDataStore
}
The combo is filled with the values from the store when I run the application, however, when I pop down the combo box, this error is thrown :
ext-debug-w-comments.js:9951 Uncaught
Ext.data.proxy.Server.buildUrl(): You are using a ServerProxy but have
not supplied it with a url.
I do not want any server proxy. These are simple locally stored name value collections.
Can JSONStores be used with combos?
If not. What is the best way to convert a JSONStore into something acceptable for the combo. I can chop, change, restructure the store object. But I just want to know if there is something simpler that I can do before going on some kind of long and pointless journey.
This problem is related 'proxy' property. Default proxy for JsonStore is 'ajax';
proxy: {
type : 'ajax',
reader: 'json',
writer: 'json'
}
You should override with 'memory' like that;
proxy: {
type: 'memory'
}
Your final store is;
Ext.create("Ext.data.JsonStore", {
data: data,
model: 'EM.model.controlUnit.CodeList',
storeId: "cl_" + tableId,
proxy: {
type: 'memory'
}
sorters: [{
sorterFn: aSorterFunction
}],
});
A JsonStore without URL is completely acceptable, but you have to make sure the combo does not trigger a load operation when clicking on the dropdown. This is done by adding to the combo definition the config option queryMode:'local':
{
xtype: 'combo',
fieldLabel: 'Marital Status',
displayField: "label",
valueField: "value",
queryMode: 'local',
store: msDataStore
}

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();
}
});

unique field in the model

i am looking for a solution to make one of the data field as unique field in the model in sencha, somehow i am not able to find documentation for it. Here is the code
Ext.define('handfree.model.CategoryM', {
extend: 'Ext.data.Model',
requires: [
'Ext.data.identifier.Uuid'
],
config: {
fields: [
{ name: 'id', type: 'int' },
{ name: 'name', type: 'string' }
],
idProperty: 'id',
identifier : 'uuid'
}
});
I need 'name' field to be unique. Thank you very much!
Assuming that you are manually popping records into a store, you can put a listener on your store, and when a record is added, unset it.
http://docs.sencha.com/touch/2-0/#!/api/Ext.data.Store-event-addrecords

Resources