![Page 2: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/2.jpg)
• Reading & saving simple dataWhen we live in a perfect world. Domain model is perfect. We decide everything.
• Real world data and demandsStill simple data but add real world scenarios and demands. Learn how to configure to cope with it.
• AssociationsHow to handle associate data.
• Multi model scenariosLearn about Ext.data.Session to track changes in multiple models and associations.
• Errors
2
Agenda
![Page 3: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/3.jpg)
Reading simple data
![Page 4: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/4.jpg)
Model View ViewModel ViewController
Sencha MVVM recap
![Page 5: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/5.jpg)
Model View ViewModel ViewController
Sencha MVVM recap
Ext.data.Model Ext.Component Ext.app.ViewModel Ext.app.ViewController
![Page 6: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/6.jpg)
Model View ViewModel ViewController
Sencha MVVM recap
Ext.data.Model Ext.Component Ext.app.ViewModel Ext.app.ViewController
View Package
![Page 7: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/7.jpg)
CRM.view.Viewport CRM.view.ViewportModel CRM.view.ViewportController
Our sample application View Package
![Page 8: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/8.jpg)
![Page 9: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/9.jpg)
resources/getCompanyById.json
• Id field is lowercase
• Date is formatted in a understandable format
{ id : 100, companyName : 'Ikea', address : 'Storgatan 1', city : 'Stockholm', country : 'Sweden',
updatedDate : '1973-11-17 05:30'}
![Page 10: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/10.jpg)
The data model
• Fields config are not really needed for simple data types.
.. except date
• Simple proxy config
Ext.define('CRM.model.CompanyProfile', { extend: 'Ext.data.Model', fields:[ {
name : 'updatedDate',type : 'date’
} ], proxy: {
url : 'resources/getCompanyById.json' }});
![Page 11: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/11.jpg)
Data loading
• linkTo function
Creates a link to a record by loading data from configured proxy and setting it on the view model with a simple name.
"companyProfile" will be our reference in all bindings referring to company data record.
Ext.define('CRM.view.ViewportController', { extend : 'Ext.app.ViewController', alias : 'controller.viewportcontroller',
init: function() {this.getViewModel().linkTo('companyProfile',{
type : 'CRM.model.CompanyProfile', id : 100 }); }});
![Page 12: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/12.jpg)
Ext.define('CRM.view.Viewport', { extend : 'Ext.Container', viewModel : 'viewportmodel', controller : 'viewportcontroller', padding : 20, items: [ { xtype : 'textfield', fieldLabel : 'Company name', bind : '{companyProfile.companyName}' }, { xtype : 'textfield', fieldLabel : 'Address', bind : '{companyProfile.address}' }
...
]});
Bind fields to view
![Page 13: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/13.jpg)
Ext.define('CRM.view.Viewport', { extend : 'Ext.Container', viewModel : 'viewportmodel', controller : 'viewportcontroller', padding : 20, items: [ '''
]});
• viewModel- connects this view to the viewmodel with
alias "viewportmodel"
• controller- connects this view to the viewController
with alias "viewportcontroller"
View configs
![Page 14: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/14.jpg)
Live demoSimple read
![Page 15: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/15.jpg)
Saving simple data
![Page 16: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/16.jpg)
Save buttonExt.define('CRM.view.ViewportController', { extend : 'Ext.app.ViewController', alias : 'controller.viewportcontroller', onSave:function(){ this.getViewModel().get('companyProfile').save(); }});
Ext.define('CRM.view.Viewport', { extend : 'Ext.Panel', viewModel : 'viewportmodel', controller : 'viewportcontroller', padding : 20, buttons:[ { text:'Save', handler:'onSave' } ], items: [ { xtype : 'textfield', fieldLabel : 'Company name', bind : '{companyProfile.companyName}' } ...
Save function
![Page 17: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/17.jpg)
Live demoSimple Read/Save
![Page 18: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/18.jpg)
HTTP Post{ "id": 100, "companyName": "Ikea AB", "address": "Storgatan 1", "city": "Malmö", "country": "Sweden", "updatedDate": "2016-08-23 19:47"}
{ id:100, companyName:"Ikea AB"}
Required response
![Page 19: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/19.jpg)
Noteworthy
• Only dirty field data was sent.
• Id was always sent
• Same URL as read
• Response data was automatically realized in view
19
![Page 20: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/20.jpg)
Real world data and demands
![Page 21: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/21.jpg)
Real world data from Customer
• Observations- id field is not "id"
{ _id : "57bb5d639baeb676ced2b0de", companyName : 'Ikea', address : {
street : 'Storgatan 1',city : 'Stockholm',country : 'Sweden'
}, updatedDate : '2016-08-23T21:26:08.358Z'
}
![Page 22: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/22.jpg)
Real world data from Customer
• Observations- id field is not "id"
- Some data resides is in objects
{ _id : "57bb5d639baeb676ced2b0de", companyName : 'Ikea', address : {
street : 'Storgatan 1',city : 'Stockholm',country : 'Sweden'
}, updatedDate : '2016-08-23T21:26:08.358Z'
}
![Page 23: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/23.jpg)
Real world data from Customer
• Observations- id field is not "id"
- Some data resides is in objects
- Date format
{ _id : "57bb5d639baeb676ced2b0de", companyName : 'Ikea', address : {
street : 'Storgatan 1',city : 'Stockholm',country : 'Sweden'
}, updatedDate : '2016-08-23T21:26:08.358Z'
}
![Page 24: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/24.jpg)
Scenarios/Customer demands
• Id must be "_id". We are using Mongo DB.
• Updated date should ignore timezones
• The exact same JSON structure must be sent on save.
• Always send all data on save.
• Save must be on separate url.
24
![Page 25: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/25.jpg)
Specify your own id field
idPropertyConsider doing this in abstract base class or even override Ext.data.Model.
Ext.define('CRM.model.CompanyProfile', { extend: 'Ext.data.Model', idProperty:'_id',
fields:[ {
name : 'updatedDate',type : 'date’
} ], proxy: {
url : 'resources/getCompanyById.json' }});
![Page 26: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/26.jpg)
Read data from nested objects
mappingSpecify a dot notated path in the fields array of data model.
fields:[ { name : 'street', mapping : 'address.street', type : 'string' }, { name : 'city', mapping : 'address.city', type : 'string' }, { name : 'country', mapping : 'address.country', type : 'string' },
... ],
![Page 27: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/27.jpg)
Send all fields on save
writeAllFieldsProxy writer configs to ensure all fields will be sent.
proxy: {type : 'ajax',url : '/companies',reader:{
type:'json'},
writer:{type : 'json',writeAllFields : true
}}
![Page 28: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/28.jpg)
Keep object nesting on save { _id : "57bb5d639baeb676ced2b0de", companyName : 'Ikea', address : {
street : 'Storgatan 1',city : 'Stockholm',
country: 'Sweden' },
updatedDate : '2016-08-23T21:26:08.358Z'}
![Page 29: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/29.jpg)
Keep object nesting on save
expandDataMakes sure the mapped field data sent back is in a nested format.
namePropertyProperty used to read the key for each value that will be sent to the server.
proxy: {type : 'ajax',url : '/companies',reader:{
type:'json'},
writer:{type : 'json',writeAllFields : true,nameProperty : 'mapping',expandData : true
}}
![Page 30: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/30.jpg)
Live demoReal world data
![Page 31: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/31.jpg)
Date should not add timezone
By default you will get a localized date in the current browsers timezone
{ _id : "57bb5d639baeb676ced2b0de", companyName : 'Ikea', address : {
street : 'Storgatan 1',city : 'Stockholm',
country: 'Sweden' },
updatedDate : '2016-08-23T21:26:08.358Z'}
![Page 32: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/32.jpg)
dateFormat
Adding the exact date format will make sure date is not altered.
fields:[ ''' { name:'updatedDate', type:'date', dateFormat:'Y-m-d\\TH:i:s.u\\Z' }],
![Page 33: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/33.jpg)
Read/Update on separate Url´s
Instead of using the proxy standard url config, we change to the more versatile api config
proxy: { type : 'ajax', url : '/companies' reader:{ type:'json' }, writer:{ type : 'json', nameProperty : 'mapping', writeAllFields : true, expandData : true } }
![Page 34: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/34.jpg)
Read/Update on separate Url´s
Instead of using the proxy standard url config, we change to the more versatile api config
proxy: { type : 'ajax', api : { read: '/companies', update: '/updateCompanies' }, reader:{ type:'json' }, writer:{ type : 'json', nameProperty : 'mapping', writeAllFields : true, expandData : true } }
![Page 35: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/35.jpg)
Associations
![Page 36: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/36.jpg)
Associated licenses{ "_id": "57bf32fe9baeb676ced2b0e1", "companyName": "Ikea", "address": { "street": "Storgatan 3", "city": "Malmö", "country": "Sweden" }, "updatedDate": "2016-08-25T18:51:39.671Z", "licenses": [ { "id": 1, "product": "ExtJS 2.1", "amount": 5 }, { "id": 2, "product": "ExtJS 4.1", "amount": 5 }, .......
]
![Page 37: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/37.jpg)
License references Company Ext.define('CRM.model.License', { extend: 'Ext.data.Model', idgen:'uuid', idProperty:'_id', fields:[ {name:'product', type:'string'}, {name:'amount', type:'float'}, {
name: 'companyId',reference: {
parent : 'CRM.model.CompanyProfile',inverse : {
role : 'licenses'}
} }
Company
License
License
License
![Page 38: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/38.jpg)
License references Company Ext.define('CRM.model.License', { extend: 'Ext.data.Model', idgen:'uuid', idProperty:'_id', fields:[ {name:'product', type:'string'}, {name:'amount', type:'float'}, {
name: 'companyId',reference: {
parent : 'CRM.model.CompanyProfile',inverse : {
role : 'licenses'}
} }
Company
License
License
License
![Page 39: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/39.jpg)
License references Company Ext.define('CRM.model.License', { extend: 'Ext.data.Model', idgen:'uuid', idProperty:'_id', fields:[ {name:'product', type:'string'}, {name:'amount', type:'float'}, {
name: 'companyId',reference: {
parent : 'CRM.model.CompanyProfile',inverse : {
role : 'licenses'}
} }
Company
License
License
License
![Page 40: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/40.jpg)
Useful?
• Automatically created stores.Company model function licenses() will return accociated licenses.
var viewModel = this.getViewModel(),companyProfile = viewModel.get('companyProfile'),store =
companyProfile.licenses();
![Page 41: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/41.jpg)
Useful?
• Automatically created stores.Company model function licenses() will return accociated licenses.
• License function getCompany() will return Company model.
var viewModel = this.getViewModel(),companyProfile = viewModel.get('licenses'),store =
companyProfile.licenses(),firstLicense = store.first(),
console.log(firstCompany.getCompany());
// Returns companyProfile
![Page 42: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/42.jpg)
Useful?
• Automatically created stores.Company model function licenses() will return accociated licenses.
• License function getCompany() will return Company model.
• Nice bindings. companyProfile.licenses references the store
{xtype : 'grid',plugins : 'cellediting',columnLines:true,bind : {
store:'{companyProfile.licenses}'},columns:[
{text: 'Licence', dataIndex:'product'}, {text: 'Amount', dataIndex:'amount'} ]}
![Page 43: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/43.jpg)
• Inline associationsLicence data is array in company JSON and should be saved in same call as company profile.
• Proxy/Remote associations Licence data is fetched from its own web service and CRUD operations are handled here
43
Possible business scenarios
![Page 44: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/44.jpg)
Inline associations{ "_id": "57bf32fe9baeb676ced2b0e1", "companyName": "Ikea", "address": { "street": "Storgatan 3", "city": "Malmö", "country": "Sweden" }, "updatedDate": "2016-08-25T18:51:39.671Z", "licenses": [ { "id": 1, "product": "ExtJS 2.1", "amount": 5 }, { "id": 2, "product": "ExtJS 4.1", "amount": 5 }, .......
]
GET
![Page 45: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/45.jpg)
Inline associations{ "_id": "57bf32fe9baeb676ced2b0e1", "companyName": "Ikea", "address": { "street": "Storgatan 3", "city": "Malmö", "country": "Sweden" }, "updatedDate": "2016-08-25T18:51:39.671Z", "licenses": [ { "id": 1, "product": "ExtJS 2.1", "amount": 5 }, { "id": 2, "product": "ExtJS 4.1", "amount": 5 }, .......
]
POST
![Page 46: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/46.jpg)
allDataOptions
Proxy writer needs to be told to save associated data.
.
proxy: { type : 'ajax',
api : { read: '/companies',
update: '/updateCompanies'},
writer:{ type : 'json', nameProperty : 'mapping', writeAllFields : true, expandData : true, allDataOptions :{ associated:true } } }
Company model
![Page 47: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/47.jpg)
Associated store data is not realized on save.
Live example
47
![Page 48: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/48.jpg)
Saving associated data in a big JSON is generally a bad idea
The associated data is probably saved in a table in a database
Empty arrays will have to force delete
48
![Page 49: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/49.jpg)
3 Possible solutions
• Re-load all data after successful save- extra call
- safe
onSave:function(){this.getViewModel().get('companyProfile').save({
callback:function(){this.getViewModel().linkTo('companyProfile',{
type : 'CRM.model.CompanyProfile', id : '57bf32fe9baeb676ced2b0e1' });
},scope:this
}); }
![Page 50: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/50.jpg)
3 Possible solutions
• Re-load all data after successful save- extra call
- safe
• Forced commitChanges()- no extra call
- response data is ignored.
onSave:function(){var store = this.getViewModel().get('companyProfile.licenses')this.getViewModel().get('companyProfile').save({
callback:function(){store.commitChanges(); },
},scope:this
});}
![Page 51: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/51.jpg)
3 Possible solutions
• Re-load all data after successful save- extra call
- safe
• Forced commitChanges()- no extra call
- response data is ignored.
• Code around it- complex
![Page 52: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/52.jpg)
What happens if license array is missing?
Demo!
52
![Page 53: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/53.jpg)
Associated stores will default to a ajax proxy.
Avoid remote reads by changing this to a memory proxy.
Ext.define('CRM.model.License', { extend: 'Ext.data.Model', fields:[ {name:'product', type:'string'}, {name:'amount', type:'float'},
{ name: 'companyId', reference: { parent : 'CRM.model.CompanyProfile', inverse : { role:'licenses', storeConfig:{ proxy:{ type:'memory' } } }
} . . .
Store config
![Page 54: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/54.jpg)
Proxy/Remote associationsExt.define('CRM.view.ViewportController', { extend : 'Ext.app.ViewController', alias : 'controller.viewportcontroller',
onSave:function(){var vm = this.getViewModel();
vm.get('companyProfile').save(); vm.get('companyProfile.licenses').sync(); },
...
• Call save() on model.
• Call sync() on stores.
![Page 55: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/55.jpg)
Proxy/Remote associationsExt.define('CRM.model.License', {
extend: 'Ext.data.Model',idProperty:'_id',fields:[..],proxy: {
type : 'ajax',api : {
read: '/licenses',create : '/addLicenses',update : '/updateLicenses',destroy : '/deleteLicenses'
}, writer:{
type : 'json', writeAllFields : true } }});
• Specify all api´s on associated data model
![Page 56: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/56.jpg)
Proxy/Remote associations{
xtype: 'grid',plugins: 'cellediting',columnLines: true,tbar: [{text: 'Add', handler: 'addLicense'}],bind: {
store: '{companyProfile.licenses}'}
},
• Associated data will only load if store is used in a binding
![Page 57: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/57.jpg)
Proxy/Remote associations
filter:[{
"property":"companyId",
"value":"57bcbaa29baeb676ced2b0e0","exactMatch":true
}]
• On read, a filter will be posted.- property is the reference name,
- value is the reference Id
Backend must honor this filter and return the correct subset.
• Live Example
HTTP GET /licenses
![Page 58: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/58.jpg)
Multi models scenarios
![Page 59: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/59.jpg)
59
![Page 60: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/60.jpg)
Ext.data.Session
The primary job of a Session is to manage a collection of records of many different types and their associations. This often starts by loading records when requested and culminates when it is time to save to the
60
![Page 61: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/61.jpg)
View with multiple models
61
Company
Licenses
Pool cars
Feedback
![Page 62: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/62.jpg)
View with multiple models
62
Company
Licenses
Pool cars
Feedback
Data model + association
![Page 63: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/63.jpg)
View with multiple models
63
Company
Licenses
Pool cars
Feedback
Data model + association
Store
![Page 64: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/64.jpg)
View with multiple models
64
Company
Licenses
Pool cars
Feedback
Data model + association
Store
Data model
![Page 65: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/65.jpg)
• getChanges()- Returns an object describing all of the modified fields, created or dropped records
maintained by this session.
- Used to track if ANY data is dirty
• getSaveBatch()- Returns an Ext.data.Batch containing the Ext.data.operation.Operation instances that are
needed to save all of the changes in this session
65
Session features
![Page 66: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/66.jpg)
One point save onSave:function(){if(this.getSession().getChanges()){
this.getSession().getSaveBatch().start();}
},
![Page 67: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/67.jpg)
Enable session Ext.define('CRM.view.Viewport', { extend : 'Ext.Panel', viewModel : 'viewportmodel', controller : 'viewportcontroller', bodyPadding : 20, session:true, buttons:[ { text:'Save', handler:'onSave' } ], layout:{ type:'vbox', align:'stretch' }, . . . .
• Enable session in view
![Page 68: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/68.jpg)
Enable session var store = this.getViewModel().getStore('cars');
store.setSession(this.getSession());• Enable session in view
• Add stores to session
![Page 69: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/69.jpg)
Enable session CRM.model.Feedback.load('57d072659baeb676ced2b0e5',{
success:function(record){this.getViewModel().set('feedback', record);
},scope:this
}, this.getSession());
• Enable session in view
• Add stores to session
• Provide session in model load
![Page 70: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/70.jpg)
Enable session this.getViewModel().linkTo('companyProfile',{type : 'CRM.model.CompanyProfile',id : '57bcbaa29baeb676ced2b0e0'
});• Enable session in view
• Add stores to session
• Provide session in model load
• Use LinkTo- uses session from viewModel
![Page 71: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/71.jpg)
Live demoMulti Model
![Page 72: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/72.jpg)
Sending extra parameters
![Page 73: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/73.jpg)
Extra proxy parameters proxy: { type : 'ajax', extraParams:{ appName:'CRM' }, api : {
read: '/companies', update: '/updateCompanies' }, reader:{ type:'json' }, writer:{ type : 'json', } }
• Set in proxy using extraParams config
![Page 74: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/74.jpg)
Extra proxy parameters var proxy = Ext.ClassManager.get(<class>).getProxy();
proxy.setExtraParam('appName', 'CRM'); • Set in proxy using extraParams config
• Set from controller using the setExtraParam function
![Page 75: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/75.jpg)
Operation parameters vm.get('companyProfile').save({params:{
appHeight:this.getView().getHeight();}
});vm.get('companyProfile.licenses').sync({
params:{appHeight:this.getView().getHeight();
}});
• Send params config into operational methods,
![Page 76: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/76.jpg)
Live demoExtra Parameters
![Page 77: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/77.jpg)
Errors with messages
![Page 78: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/78.jpg)
Handle error response { "IsSuccess": false, "ErrorMessage": "Missing company"}Error returned from the server in a json
response when logic fails or data is missing.
![Page 79: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/79.jpg)
Configure the proxy reader proxy: {type : 'ajax',api : {
read: '/companies',update: '/updateCompanies'
},reader:{
type:'json',successProperty:'IsSuccess',messageProperty:'ErrorMessage'
}
. . .
• successProperty
The property indicating that the operation was successful or not.
• messageProperty
The property where the error message is returned.
![Page 80: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/80.jpg)
Listen for proxy exception Ext.mixin.Observable.observe(Ext.data.proxy.Server);
Ext.data.proxy.Server.on('exception',function(proxy, resp, operation){
Ext.Msg.alert('Error', operation.getError());
});
• exception- fires when "success" is false
- fires on HTTP exceptions
• operation.getError()- returns messageProperty content
![Page 81: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/81.jpg)
Live demoError handling
![Page 82: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/82.jpg)
Please Take the Survey in the Mobile App
• Navigate to this session in the mobile app
• Click on “Evaluate Session”
• Respondents will be entered into a drawing to win one of five $50 Amazon gift cards
![Page 83: SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling](https://reader037.vdocuments.us/reader037/viewer/2022110218/5876fe7a1a28abf3398b6cff/html5/thumbnails/83.jpg)