I feel like I may be over complicating this. Please feel free to send me in a different direction.
I'm trying to load an array of records (the values) with only values, into model objects, using the fields defined in my model (the keys).
My Model
Ext.define('MyApp.model.AppData', {
extend: 'Ext.data.Model',
fields: [
{name: 'key'},
{name: 'value'},
{name: 'desc'},
{name: 'index', type: 'int'},
{name: 'type'}
]
});
My Store
Ext.define('MyApp.store.AppData', {
extend: 'Ext.data.ArrayStore',
groupField: 'type',
model: 'MyApp.model.AppData',
autoload: false,
constructor: function (config) {
var data = [
['val1', 'val2', 'val3', 'val4', 'val5'],
['val1', 'val2', 'val3', 'val4', 'val5'],
...
];
this.loadData(data);
}
});
So the end goal here is to have my data in the store looking like
[
{'key':'val1', 'value':'val2', 'desc':'val3', 'index':'val4', 'type':'val5'},
{...},
{...}
]
Currently getting a 'me.removed is undefined' error. I know its related to the loadData() function. Which makes me feel like I'm not using this correctly somewhere.
I could just hardcode the data formatted with the key value pairs... but that just feels unmaintainable and wrong way to do this.
Thanks!
You can just use store's data config:
var myModel=Ext.define('MyApp.model.AppData', {
extend: 'Ext.data.Model',
fields: [
{name: 'key'},
{name: 'value'},
{name: 'desc'},
{name: 'index', type: 'int'},
{name: 'type'}
]
});
var myData = [
['val1', 'val2', 'val3', 0, 'val5'],
['val1', 'val2', 'val3', 1, 'val5']
];
var store = Ext.create('Ext.data.ArrayStore', {
model:myModel,
data:myData
});
Here's a working fiddle
Related
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
})
});
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();
}
});
I have JSON in the following format:
{
"id": 1,
"arbitraryAttribute": "arbitraryValue",
"thing": {
"thingKey1": "thingValue1",
"thinkKey2": "thingValue2"
}
}
This model is represented like so:
Ext.define("MyModel", {
extends: "Ext.data.Model",
fields: [
{name: "id", type: "string"},
{name: "arbitraryAttribute", type: "string"},
],
hasOne: [
{
model: "Thing",
name: "thing"
}
]
});
Ext.define("Thing", {
extends: "Ext.data.Model",
fields: [
{name: "thingKey1", type: "string"},
{name: "thingKey2", type: "string"}
]
});
The proxy is a simple json proxy. The JSON it is getting looks like that which I presented, but my record seems to have no knowledge of the Thing model. Is there any additional plumbing I need to set up to get MyModel to pull the nested Thing json?
Your forgot to set the thing_id in MyModel. Also this doesnt work at all in ExtJs.
You can now set the thing_id via JSON but not the whole object as you do (and it should).
It will autoLoad the complete object via the models proxy if required.
Ext.define('User', {
extend:'Ext.data.Model',
fields: ['id', 'name', 'status'],
associations: [
{ type: 'hasOne', model: 'Status', associationKey: 'status' }
]
});
Ext.define('Status', {
extend:'Ext.data.Model',
fields: ['id', 'title'],
});
Demo here
How can i fetch a record using belongs to association ?
var Category = Ext.regModel('Category', {
fields: [
{name: 'id', type: 'int'},
{name: 'name', type: 'string'}
]
});
var Product = Ext.regModel('Product', {
fields: [
{name: 'id', type: 'int'},
{name: 'category_id', type: 'int'},
{name: 'name', type: 'string'}
],
associations: [
{type: 'belongsTo', model: 'Category'}
]
});
Amol,
I speak only of ExtJS 4, so if you can relate this to ExtJS 3 then great, but you would retrieve multiple records via a store:
As a starting point though you could do
var records = Ext.StoreManager.lookupStore("productStore").load({
belongTo: 'books',
callback: function(records) {
Ext.each(records,function(record) {
console.log(JSON.stringify(record.raw))
});
}
});
Depending on the proxy setup on the productStore, this will append belongTo to the querystring so if reader proxy has url: /products and the extra params belongTo is sent this will hit the server with /products?belongTo=books
I just downloaded the final version of ExtJs 4 and I'm trying to implement some things using new Model approach.
For instance I have a model named SetupModel, it has 2 nested models Users, Reports.
I create new store and I set the Model property of the store = SetupModel.
The question is - how can I access my nested properties after data was loaded into the store?
I need something like myStore.data.Users(), but is incorrect.
Any thoughts?
When you define your model, you need to provide the necessary association with the nested models. Since, you have not provided your code. Here is an example:
My Product Model:
Product = Ext.define('Product',{
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
{name: 'user_id', type: 'int'},
{name: 'name', type: 'string'},
{name: 'price', type: 'float'}
],
proxy: {
type: 'localstorage',
id: 'products'
}
});
My User Model:
User = Ext.define('User',{
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
{name: 'name', type: 'string'},
{name: 'gender', type: 'string'},
{name: 'username', type: 'string'}
],
associations: [
{type: 'hasMany', model: 'Product', name: 'products'}
],
proxy: {
type: 'localstorage',
id : 'users'
}
});
Now, if you have a instance of User model with products. Here is how you can access the products:
var productStore = user.products();
Note that user.products() returns a Ext.data.Store. Now, you can traverse or filter or find your product record. Here is how I got my first product's name:
productStore.getAt(0).get('name');