Mapping not working when creating a model with Ext.create? - extjs

When I create a model using Ext.create() in ExtJs 4.2+, I am expecting the mapping to fill the model but it does not seem to do it. Is it a normal behavior?
If I use a model with mapping in a store, the mapping works fine...
Example not working:
http://jsfiddle.net/B6v6v/
Ext.define('MyApp.model.file', {
extend: 'Ext.data.Model',
fields: [
{
name: 'name',
mapping:'label'
}]
});
var rec = Ext.create("MyApp.model.file",{"label":"TEST"});
console.log(rec.get("name"));

Yes, it's normal. The mapping is for transforming data coming in from the server into something readable in your model. If you already have the data, why not just use the correct key?
If you must, you can do something like:
MyApp.model.File.getProxy().getReader().readRecords([{}, {}, {}]);

Related

How come store.add() method does not perform mapping?

I have a nested json data, namely:
{
name: 'alex',
tel: {
personal: '347xxxx',
work: '331xxxx'
}
}
Then the following model:
Ext.define("Employer", {
extend: 'Ext.data.Model',
idProperty: 'personalTel',
fields: [...
{name: 'personalTel', mapping: 'tel.personal'}
Finally the following store:
Ext.create('Ext.data.Store',{
model: 'Employer',
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'root'
}
},
data: myInitialData //an array containing json objects
As long as the data is contained in myInitialData the personalTel field is correctly set.
However, adding a new record to the store does not trigger the mapping and so I find myself with strange personalTel property, that is automatic IDs extjs puts!
ExtJS allows you to load multiple models via nesting when using a reader. It does not allow those models to be created when instantiating the model directly, which is what adding the object to the store does.
The idea is that each model is treated separately with its own store. Want to add a customer with a telephone number? Create the telephone number first, put it in its store, then create the customer with a reference to the telephone number.
This approach is a bit clumsy, though, and only works with models that really are separate entities.
An alternative approach would be to use a custom type, or simply to use the 'auto' type (which treats the data as a blob that you can do what you want with). Both approaches have their drawbacks.

Map JSON Object to Model/Store

I'm using Worklight framework to construct a mobile app for IOS, and is using Sencha Touch 2.3 to build the app.
Due to the environment, i cannot use proxy in Sencha Touch Store/Model objects to load data from the server, as i would need to use Worklight's adapter to retrieve the info. I have managed to do that using some boilerplate codes.
However, i wish that i could utilize the Sencha Model more, and as such, am thinking whether it is possible for me to load a JSON object into the Model object automatically, without specifying a proxy.
Currently i'm doing a lot of loop and setter call to load the data from the JSON object to a model, like below:
var profile = Ext.create('Profile', {
Id: rawProfile.Id,
Name: rawProfile.Name
Age: rawProfile.Age
.....
}
where rawProfile is the JSON object i loaded from the server.
Any way i can make this cleaner?
You could create a Model class which would contain the data contained in your rawProfile object.
Ext.define('MyModel', {
extend: 'Ext.data.Model',
fields: [{
name: 'Id',
name: 'Age',
...
}],
proxy: {
type: 'memory',
reader: 'json'
}
});
I've also set an in memory proxy which will read json objects.
You could then create a Store which would use the model you defined and the in memory proxy (meaning you wouldn't be using Ext's build in ajax messaging).
Ext.create('MyStore', {
model: 'MyModel',
autoLoad: false
});
Setting the autoLoad to be false, as you want to get the data from a different source.
Therefore, once you have your json object you can load it into the store by calling store.loadRawData(jsonObject).
In this case, the jsonObject would be the object containing all the json objects returned from the server, meaning that your code doesn't have to handle iterating through the records and you can leave it to the Sencha classes.
However you would need to figure out the writing data back to the server.
I'd recommend running through the Sencha Data Package tutorial as it gives a good intro to the data package
If all the fields map 1:1 with the json object, you can do this:
var profile = Ext.create('Profile', rawProfile);
Alternatively (or to avoid the convert functions for fields to be called), you can directly set the data property on the created model.
var profile = Ext.create('Profile');
profile.data = rawProfile;
Again, this requires a 1:1 on the fields and json object.

Model alias in ExtJs

I have definition of my model. Here is:
Ext.define('KP.model.account.AccountList', {
extend: 'Ext.data.Model',
alias: 'model.d_AccountList',
fields: ['key', 'number', 'personal_account', 'full_name', 'adress', 'pu']
});
So, I want to create this model by alias.
Or define store, what use this model like this:
model: 'd_AccountList'
How can I do that?
Thanks!
P.S.:Maybe my alias is wrong...
As far as I'm aware of there is none.
I think you can't create an alias for model, there is not alias property on Ext.data.Model.
http://docs.sencha.com/ext-js/4-1/#!/api/Ext.data.Model
Ext.define('model.d_AccountList', {
extend: 'Ext.data.Model',
fields: ['key', 'number', 'personal_account', 'full_name', 'adress', 'pu']
});
var accountList = Ext.Create('model.d_AccountList', {
key: 11,
number: 33,
personal_account: 4553463
})
Folks,
The 'alias' member is existent to all ExtJS classes that inherit from Ext.Class. That includes models. You can use whatever alias you want as long as it does not collide with other ones. It's best if you divide them by domain. There are already some domains out there like 'widget','store,'proxy'. Whether you need to specify the domain or the full alias depends on instantiating class when using the alias config. For instance, if you refer to a proxy with alias of 'proxy.myProxyAlias', in a store you should use:
proxy:'myProxyAlias'
Reason being is that the the Ext.data.Store class will automatically pre-pend 'proxy.'. There are few others that are doing the same trick:
defining 'reader' from association
defining 'writer'/'reader' from a proxy
defining 'reader' from a form
defining 'axis'/'series' from a chart
defining 'proxy'/another 'store' from a store
defining a 'widget'
In your case that you use really gives you that trick for model classes, so if you define a model with alias:
alias: 'model.myModel'
on the store you'll have to use either the full model class name or:
xtype: 'model.myModel'
Hope it helps.

ExtJS 4 Change grid store on the fly

Is it posible to change grid's store in ExtJS 4?
For example, i have two models:
User = Ext.define('User',{
extend: 'Ext.data.Model',
[...],
hasMany: 'Product'
});
Product = Ext.define('Product',{
extend: 'Ext.data.Model',
[...]
});
and two grids.
The first grid is linked with Store which uses User model and loads nested json data from backend, like
{
users: [{
id: 1,
products: [
{id: 1},
{id: 2}
]
}, {
id: 2,
products: [
{id: 3},
{id: 4},
{id: 5}
]
}]
}
All i want to get is when you click on the row in the first grid, the second grid must show products of the user, without connection to the server.
All i know is that user.products(); returns a Ext.data.Store object.
So the idea is to change second grid's store to user.products();, but there is no such method grid.setStore() :-)
Thanks in advance
I think a better solution would be to :
grid1.on('itemclick', function(view, record) {
grid2.reconfigure(record.products());
);
You are looking at stores the wrong way. A store is attached to the grid forever, hence there is no grid.setStore(). You do NOT change a store for a grid, instead you change the DATA in the store for that grid.
Now, solution to your problem: You are correct with the part that you already have a instance of store with your data. ie; user.products(). Still, you will have to create a store for your grid. This store will not have any data though. Now, when you need to display products information, you need to load the grid's store with data. You can use:
load()
loadData()
loadRecord()
to load data into your store. In your case, you can do the following:
myStore = user.products();
grid.getStore().loadRecords(myStore.getRange(0,myStore.getCount()),{addRecords: false});
If you want to attach a store to a grid after the grid has been created, you can use the bindStore() method.
var store = user.products();
grid.getView().bindStore(store);
Alternatively you can also use load(), loadData(), loadRecords() methods, and copy the data into your store.
Abdel Olakara's answer helped me out when I needed to update data on something that didn't have reconfigure (custom class inheriting from Ext.form.FieldSet).
But you don't need to specify addRecords or the range for getRange, because the defaults have us covered in this case.
This means you can do:
myStore = user.products();
grid.getStore().loadRecords(myStore.getRange());

Dynamic Model with ExtJS 4

With ExtJS 3.x, I was able to use the "fields" property of a Store, but it seems with ExtJS 4 I have to absolutely use a Model. It's fine, but in my case, it's not a static Model, and I need to define the fields on the fly and sometimes to change them.
I could re-create a Model, but I need to use a different name as it's apparently not possible to modify an exisiting Model, neither delete it. If I try to use Ext.regModel with the same name, ExtJS crashes.
Thanks for your help!
4.1 UPDATE:
As an update... in 4.1 there is now a static method setFields which can be used to define the model prototype fields. It works well in a controller's init method.
When I did this, I wanted to have some static fields defined in the model class and then set some more dynamically. Unfortunately the new setFields method replaces all fields with the argument, it was easy enough to handle though.
This example uses the MVC pattern where my model and store are included in the controller's model array and store array (providing me with the handy getters used below):
Ext.define('ST.controller.Main', {
extend: 'Ext.app.Controller',
models: ['User', 'Reference'],
stores: ['CurrentUser', 'PermissionRef'],
views: ['MainPanel'],
init: function() {
var me = this;
me.getPermissionRefStore().on('load', function(store, records) {
var model = me.getUserModel();
// this returns the static fields already defined
// in my User model class
fields = model.prototype.fields.getRange();
// add the permission options (dynamic fields) to the static fields
Ext.each(records, function(permission) {
fields.push({name: permission.get('name'), type: 'bool'});
});
// 4.1 method to update the User model fields
model.setFields(fields);
// now load the current user (it will use the updated model)
me.getCurrentUserStore().load();
});
}
});
The User model and CurrentUser store are created exactly like regular, non-dynamic models and stores would be and included in their respective controller arrays, the 'User' model is simply missing the dynamic fields which are added as shown above.
I also went into that problem. I have a service which is responsible for fetching metadata from the server and adapting the models and stores to this metadata.
I therefore defined an empty model and configured the store to use this model.
When the meta data is processed, I add the new/additional fields to the prototype of the model like this (metaDataStore is the store containing the meta data, model is the model which can be obtained from the model manager):
var fields = [];
metaDataStore.each(function(item) {
fields.push(Ext.create('Ext.data.Field', {
name: item.get('field')
}));
});
model.prototype.fields.removeAll();
model.prototype.fields.addAll(fields);
When I then call load on a store using this model or create new model instances the new fields are processed correctly.
Here's a very simple example. Just use a normal Ext.data.Store but instead of a model, specify the fields property:
// you can specify a simple string ('totally')
// or an object with an Ext.data.Field ('dynamic')
var fields = ['totally', {name : 'dynamic', type : 'string'}];
var newStore = new MyApp.store.Object({
fields : fields
// other options like proxy, autoLoad...
});
Don't specify a model property - it seems that it would override the fields property.
I also wanted to change the columns and content of an existing grid dynamically:
// reconfigure the grid to use the new store and other columns
var newColumns = [
{header: 'Totally', dataIndex: 'totally'},
{header: 'Dynamic', dataIndex: 'dynamic'}
];
myGrid.reconfigure(newStore, newColumns);
From the Ext JS 4 documentation about the "fields" property of Ext.data.Store:
This may be used in place of
specifying a model configuration. The
fields should be a set of
Ext.data.Field configuration objects.
The store will automatically create a
Ext.data.Model with these fields. In
general this configuration option
should be avoided, it exists for the
purposes of backwards compatibility.
For anything more complicated, such as
specifying a particular id property or
assocations, a Ext.data.Model should
be defined and specified for the model
config.
So be careful - Sencha may remove it in the future.

Resources