Handle real world data
with confidence.
Fredric Berling
@FredricBerling
fredric@entence.se
• Reading & saving simple data
When we live in a perfect world. Domain model is perfect. We decide everything.
• Real world data and demands
Still simple data but add real world scenarios and demands. Learn how to configure to cope with it.
• Associations
How to handle associate data.
• Multi model scenarios
Learn about Ext.data.Session to track changes in multiple models and associations.
• Errors
2
Agenda
Reading simple data
Model View ViewModel ViewController
Sencha MVVM recap
Model View ViewModel ViewController
Sencha MVVM recap
Ext.data.Model Ext.Component Ext.app.ViewModel Ext.app.ViewControlle
r
Model View ViewModel ViewController
Sencha MVVM recap
Ext.data.Model Ext.Component Ext.app.ViewModel Ext.app.ViewControlle
r
View Package
CRM.view.Viewport CRM.view.ViewportModel CRM.view.ViewportController
Our sample application
View Package
SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling
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'
}
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'
}
});
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
});
}
});
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
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
Live demo
Simple read
Saving simple data
Save button
Ext.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
Live demo
Simple
Read/Save
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
Noteworthy
• Only dirty field data was sent.
• Id was always sent
• Same URL as read
• Response data was automatically realized in view
19
Real world data and demands
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'
}
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'
}
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'
}
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
Specify your own id field
idProperty
Consider 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'
}
});
Read data from nested objects
mapping
Specify 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'
},
...
],
Send all fields on save
writeAllFields
Proxy writer configs to ensure all fields
will be sent.
proxy: {
type : 'ajax',
url : '/companies',
reader:{
type:'json'
},
writer:{
type : 'json',
writeAllFields : true
}
}
Keep object nesting on save
{
_id : "57bb5d639baeb676ced2b0de",
companyName : 'Ikea',
address : {
street : 'Storgatan 1',
city : 'Stockholm',
country: 'Sweden'
},
updatedDate : '2016-08-23T21:26:08.358Z'
}
Keep object nesting on save
expandData
Makes sure the mapped field data sent
back is in a nested format.
nameProperty
Property 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
}
}
Live demo
Real world data
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'
}
dateFormat
Adding the exact date format will make
sure date is not altered.
fields:[
'''
{
name:'updatedDate',
type:'date',
dateFormat:'Y-m-dTH:i:s.uZ'
}
],
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
}
}
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
}
}
Associations
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
},
.......
]
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
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
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
Useful?
• Automatically created stores.
Company model function licenses() will return
accociated licenses.
var viewModel = this.getViewModel(),
companyProfile = viewModel.get('companyProfile'),
store = companyProfile.licenses();
Useful?
• Automatically created stores.
Company model function licenses() will return
accociated licenses.
• License function getCompany() will
return Company model.
varviewModel = this.getViewModel(),
companyProfile = viewModel.get('licenses'),
store = companyProfile.licenses(),
firstLicense = store.first(),
console.log(firstCompany.getCompany());
// Returns companyProfile
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'}
]
}
• Inline associations
Licence 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
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
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
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
Associated store data is not realized on save.
Live example
47
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
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
});
}
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
});
}
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
What happens if license array is missing?
Demo!
52
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
Proxy/Remote associations
Ext.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.
Proxy/Remote associations
Ext.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
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
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
Multi models scenarios
59
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
View with multiple models
61
Company
Licenses
Pool cars
Feedback
View with multiple models
62
Company
Licenses
Pool cars
Feedback
Data model + association
View with multiple models
63
Company
Licenses
Pool cars
Feedback
Data model + association
Store
View with multiple models
64
Company
Licenses
Pool cars
Feedback
Data model + association
Store
Data model
• 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
One point save onSave:function(){
if(this.getSession().getChanges()){
this.getSession().getSaveBatch().start();
}
},
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
Enable session var store = this.getViewModel().getStore('cars');
store.setSession(this.getSession());
• Enable session in view
• Add stores to session
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
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
Live demo
Multi Model
Sending extra parameters
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
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
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,
Live demo
Extra Parameters
Errors with messages
Handle error response {
"IsSuccess": false,
"ErrorMessage": "Missing company"
}Error returned from the server in a json
response when logic fails or data is
missing.
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.
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
Live demo
Error handling
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
SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling

More Related Content

PPT
SenchaCon 2016: Add Magic to Your Ext JS Apps with D3 Visualizations - Vitaly...
PPTX
SenchaCon 2016: Keynote Presentation - Art Landro, Gautam Agrawal, Mark Brocato
PPTX
SenchaCon 2016: Improve Workflow Driven Applications with Ext JS Draw Package...
PPTX
JavaScript Objects and OOP Programming with JavaScript
PDF
GWT.create 2013: Introduction to GXT
PDF
Start your app the better way with Styled System
PPTX
AngularJS
PDF
Contagion的Ruby/Rails投影片
 
SenchaCon 2016: Add Magic to Your Ext JS Apps with D3 Visualizations - Vitaly...
SenchaCon 2016: Keynote Presentation - Art Landro, Gautam Agrawal, Mark Brocato
SenchaCon 2016: Improve Workflow Driven Applications with Ext JS Draw Package...
JavaScript Objects and OOP Programming with JavaScript
GWT.create 2013: Introduction to GXT
Start your app the better way with Styled System
AngularJS
Contagion的Ruby/Rails投影片
 

What's hot (20)

PDF
Dig Deeper into WordPress - WD Meetup Cairo
PDF
MongoDB .local Munich 2019: Aggregation Pipeline Power++: How MongoDB 4.2 Pip...
PPTX
IndexedDB - Querying and Performance
PDF
MongoDB .local London 2019: Tips and Tricks++ for Querying and Indexing MongoDB
PPT
JavaScript JQUERY AJAX
PDF
Autopsy Of A Widget
PDF
MongoDB .local Munich 2019: Tips and Tricks++ for Querying and Indexing MongoDB
PDF
Rapid Prototyping with PEAR
PDF
Drupal 8: Fields reborn
PDF
OpenERP Technical Memento
PDF
Databinding and Performance-Tuning in Angular 2
PDF
MongoDB With Style
PPTX
Build a better UI component library with Styled System
PDF
MongoDB .local Paris 2020: La puissance du Pipeline d'Agrégation de MongoDB
PPT
03DOM.ppt
PDF
Kief Morris - Infrastructure is terrible
PDF
What's new in iOS 7
PDF
GQL cheat sheet latest
PDF
GQL CheatSheet 1.1
PDF
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
Dig Deeper into WordPress - WD Meetup Cairo
MongoDB .local Munich 2019: Aggregation Pipeline Power++: How MongoDB 4.2 Pip...
IndexedDB - Querying and Performance
MongoDB .local London 2019: Tips and Tricks++ for Querying and Indexing MongoDB
JavaScript JQUERY AJAX
Autopsy Of A Widget
MongoDB .local Munich 2019: Tips and Tricks++ for Querying and Indexing MongoDB
Rapid Prototyping with PEAR
Drupal 8: Fields reborn
OpenERP Technical Memento
Databinding and Performance-Tuning in Angular 2
MongoDB With Style
Build a better UI component library with Styled System
MongoDB .local Paris 2020: La puissance du Pipeline d'Agrégation de MongoDB
03DOM.ppt
Kief Morris - Infrastructure is terrible
What's new in iOS 7
GQL cheat sheet latest
GQL CheatSheet 1.1
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
Ad

Viewers also liked (20)

PPTX
SenchaCon 2016: How to Give your Sencha App Real-time Web Performance - James...
PPT
SenchaCon 2016: LinkRest - Modern RESTful API Framework for Ext JS Apps - Rou...
PPTX
SenchaCon 2016: Creating a Flexible and Usable Industry Specific Solution - D...
PPTX
SenchaCon 2016: Refine Enterprise Applications by Focusing on U0ser Experienc...
PPTX
SenchaCon 2016: Turbocharge your Ext JS App - Per Minborg, Anselm McClain, Jo...
PPTX
SenchaCon 2016: Developing and Delivering Quality Code, Frequently - Neil Manvar
PPTX
SenchaCon 2016: JavaScript is Great but Stop Writing It - Rory Hardy
PPTX
SenchaCon 2016: Mobile First? Desktop First? Or Should you Think Universal Ap...
PPTX
SenchaCon 2016: Integrating Geospatial Maps & Big Data Using CartoDB via Ext ...
PPT
SenchaCon 2016: Expect the Unexpected - Dealing with Errors in Web Apps
PPTX
SenchaCon 2016: How to Auto Generate a Back-end in Minutes - Per Minborg, Emi...
PPTX
SenchaCon 2016: Handling Undo-Redo in Sencha Applications - Nickolay Platonov
PPTX
Ext JS Architecture Best Practices - Mitchell Simeons
PPTX
Building Ext JS Using HATEOAS - Jeff Stano
PPTX
SenchaCon 2016: Upgrading an Ext JS 4.x Application to Ext JS 6.x - Mark Linc...
PPTX
SenchaCon 2016: Accessibility, Teamwork & Ext JS: A Customer Success Story - ...
PPTX
SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin
PPTX
SenchaCon 2016: The Modern Toolchain - Ross Gerbasi
PPTX
SenchaCon 2016: Using Ext JS 6 for Cross-Platform Development on Mobile - And...
PPTX
SenchaCon 2016: Building a Faceted Catalog of Video Game Assets Using Ext JS ...
SenchaCon 2016: How to Give your Sencha App Real-time Web Performance - James...
SenchaCon 2016: LinkRest - Modern RESTful API Framework for Ext JS Apps - Rou...
SenchaCon 2016: Creating a Flexible and Usable Industry Specific Solution - D...
SenchaCon 2016: Refine Enterprise Applications by Focusing on U0ser Experienc...
SenchaCon 2016: Turbocharge your Ext JS App - Per Minborg, Anselm McClain, Jo...
SenchaCon 2016: Developing and Delivering Quality Code, Frequently - Neil Manvar
SenchaCon 2016: JavaScript is Great but Stop Writing It - Rory Hardy
SenchaCon 2016: Mobile First? Desktop First? Or Should you Think Universal Ap...
SenchaCon 2016: Integrating Geospatial Maps & Big Data Using CartoDB via Ext ...
SenchaCon 2016: Expect the Unexpected - Dealing with Errors in Web Apps
SenchaCon 2016: How to Auto Generate a Back-end in Minutes - Per Minborg, Emi...
SenchaCon 2016: Handling Undo-Redo in Sencha Applications - Nickolay Platonov
Ext JS Architecture Best Practices - Mitchell Simeons
Building Ext JS Using HATEOAS - Jeff Stano
SenchaCon 2016: Upgrading an Ext JS 4.x Application to Ext JS 6.x - Mark Linc...
SenchaCon 2016: Accessibility, Teamwork & Ext JS: A Customer Success Story - ...
SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin
SenchaCon 2016: The Modern Toolchain - Ross Gerbasi
SenchaCon 2016: Using Ext JS 6 for Cross-Platform Development on Mobile - And...
SenchaCon 2016: Building a Faceted Catalog of Video Game Assets Using Ext JS ...
Ad

Similar to SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling (20)

PDF
MongoDB Schema Design (Event: An Evening with MongoDB Houston 3/11/15)
PPTX
Sencha Touch - Introduction
PPTX
Sencha ExtJs Learning Part 2 - MVC And MVVM Architecture in ExtJs [ENGLISH]
PDF
A mobile web app for Android in 75 minutes
PPTX
A Customer-Centric Banking Platform Powered by MongoDB
PPT
Serious Sencha - Data Layer and Server-Side REST Interface
PDF
Aprimorando sua Aplicação com Ext JS 4 - BrazilJS
PDF
10-Step Methodology to Building a Single View with MongoDB
PDF
JDD2014: REST API versioning practice: from header to model - Łukasz Wierzbicki
PPTX
Database Trends for Modern Applications: Why the Database You Choose Matters
PDF
Dynamics 365 CRM Javascript Customization
PDF
Angular.js is super cool
KEY
MVC on the server and on the client
PDF
MVC on the Server and on the Client: How to Integrate Spring MVC and Backbone...
PPTX
Ext JS Introduction
KEY
Intro to IndexedDB (Beta)
PDF
Create a mobile web app with Sencha Touch
PPTX
Webinar: How Financial Firms Create a Single Customer View with MongoDB
PPTX
Designing a ui for microservices @ .NET Day Switzerland 2019
PPT
Webinar: Making A Single View of the Customer Real with MongoDB
MongoDB Schema Design (Event: An Evening with MongoDB Houston 3/11/15)
Sencha Touch - Introduction
Sencha ExtJs Learning Part 2 - MVC And MVVM Architecture in ExtJs [ENGLISH]
A mobile web app for Android in 75 minutes
A Customer-Centric Banking Platform Powered by MongoDB
Serious Sencha - Data Layer and Server-Side REST Interface
Aprimorando sua Aplicação com Ext JS 4 - BrazilJS
10-Step Methodology to Building a Single View with MongoDB
JDD2014: REST API versioning practice: from header to model - Łukasz Wierzbicki
Database Trends for Modern Applications: Why the Database You Choose Matters
Dynamics 365 CRM Javascript Customization
Angular.js is super cool
MVC on the server and on the client
MVC on the Server and on the Client: How to Integrate Spring MVC and Backbone...
Ext JS Introduction
Intro to IndexedDB (Beta)
Create a mobile web app with Sencha Touch
Webinar: How Financial Firms Create a Single Customer View with MongoDB
Designing a ui for microservices @ .NET Day Switzerland 2019
Webinar: Making A Single View of the Customer Real with MongoDB

More from Sencha (14)

PDF
Breathe New Life into Your Existing JavaScript Applications with Web Components
PDF
Ext JS 6.6 Highlights
PDF
Sencha Roadshow 2017: BufferedStore Internals featuring eyeworkers interactiv...
PDF
Sencha Roadshow 2017: Build Progressive Web Apps with Ext JS and Cmd
PDF
Sencha Roadshow 2017: Best Practices for Implementing Continuous Web App Testing
PDF
Sencha Roadshow 2017: What's New in Sencha Test
PDF
Sencha Roadshow 2017: Sencha Upgrades - The Good. The Bad. The Ugly - Eva Luc...
PDF
Sencha Roadshow 2017: Modernizing the Ext JS Class System and Tooling
PDF
Sencha Roadshow 2017: Sencha Best Practices: Coworkee App
PDF
Sencha Roadshow 2017: Mobile First or Desktop First
PDF
Sencha Roadshow 2017: Innovations in Ext JS 6.5 and Beyond
PDF
Leveraging React and GraphQL to Create a Performant, Scalable Data Grid
PDF
Learn Key Insights from The State of Web Application Testing Research Report
PPTX
Introducing ExtReact: Adding Powerful Sencha Components to React Apps
Breathe New Life into Your Existing JavaScript Applications with Web Components
Ext JS 6.6 Highlights
Sencha Roadshow 2017: BufferedStore Internals featuring eyeworkers interactiv...
Sencha Roadshow 2017: Build Progressive Web Apps with Ext JS and Cmd
Sencha Roadshow 2017: Best Practices for Implementing Continuous Web App Testing
Sencha Roadshow 2017: What's New in Sencha Test
Sencha Roadshow 2017: Sencha Upgrades - The Good. The Bad. The Ugly - Eva Luc...
Sencha Roadshow 2017: Modernizing the Ext JS Class System and Tooling
Sencha Roadshow 2017: Sencha Best Practices: Coworkee App
Sencha Roadshow 2017: Mobile First or Desktop First
Sencha Roadshow 2017: Innovations in Ext JS 6.5 and Beyond
Leveraging React and GraphQL to Create a Performant, Scalable Data Grid
Learn Key Insights from The State of Web Application Testing Research Report
Introducing ExtReact: Adding Powerful Sencha Components to React Apps

Recently uploaded (20)

PDF
The-2025-Engineering-Revolution-AI-Quality-and-DevOps-Convergence.pdf
PPTX
GROUP4NURSINGINFORMATICSREPORT-2 PRESENTATION
PPTX
Custom Battery Pack Design Considerations for Performance and Safety
PDF
Advancing precision in air quality forecasting through machine learning integ...
PDF
Transform-Your-Factory-with-AI-Driven-Quality-Engineering.pdf
PDF
NewMind AI Weekly Chronicles – August ’25 Week IV
PDF
Transform-Your-Streaming-Platform-with-AI-Driven-Quality-Engineering.pdf
PDF
Convolutional neural network based encoder-decoder for efficient real-time ob...
PPT
Galois Field Theory of Risk: A Perspective, Protocol, and Mathematical Backgr...
PDF
CXOs-Are-you-still-doing-manual-DevOps-in-the-age-of-AI.pdf
PPTX
Build Your First AI Agent with UiPath.pptx
PDF
Early detection and classification of bone marrow changes in lumbar vertebrae...
PPTX
MuleSoft-Compete-Deck for midddleware integrations
PDF
Taming the Chaos: How to Turn Unstructured Data into Decisions
PDF
Dell Pro Micro: Speed customer interactions, patient processing, and learning...
PDF
AI.gov: A Trojan Horse in the Age of Artificial Intelligence
PDF
Accessing-Finance-in-Jordan-MENA 2024 2025.pdf
PDF
4 layer Arch & Reference Arch of IoT.pdf
PDF
Improvisation in detection of pomegranate leaf disease using transfer learni...
PDF
Rapid Prototyping: A lecture on prototyping techniques for interface design
The-2025-Engineering-Revolution-AI-Quality-and-DevOps-Convergence.pdf
GROUP4NURSINGINFORMATICSREPORT-2 PRESENTATION
Custom Battery Pack Design Considerations for Performance and Safety
Advancing precision in air quality forecasting through machine learning integ...
Transform-Your-Factory-with-AI-Driven-Quality-Engineering.pdf
NewMind AI Weekly Chronicles – August ’25 Week IV
Transform-Your-Streaming-Platform-with-AI-Driven-Quality-Engineering.pdf
Convolutional neural network based encoder-decoder for efficient real-time ob...
Galois Field Theory of Risk: A Perspective, Protocol, and Mathematical Backgr...
CXOs-Are-you-still-doing-manual-DevOps-in-the-age-of-AI.pdf
Build Your First AI Agent with UiPath.pptx
Early detection and classification of bone marrow changes in lumbar vertebrae...
MuleSoft-Compete-Deck for midddleware integrations
Taming the Chaos: How to Turn Unstructured Data into Decisions
Dell Pro Micro: Speed customer interactions, patient processing, and learning...
AI.gov: A Trojan Horse in the Age of Artificial Intelligence
Accessing-Finance-in-Jordan-MENA 2024 2025.pdf
4 layer Arch & Reference Arch of IoT.pdf
Improvisation in detection of pomegranate leaf disease using transfer learni...
Rapid Prototyping: A lecture on prototyping techniques for interface design

SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling

  • 1. Handle real world data with confidence. Fredric Berling @FredricBerling [email protected]
  • 2. • Reading & saving simple data When we live in a perfect world. Domain model is perfect. We decide everything. • Real world data and demands Still simple data but add real world scenarios and demands. Learn how to configure to cope with it. • Associations How to handle associate data. • Multi model scenarios Learn about Ext.data.Session to track changes in multiple models and associations. • Errors 2 Agenda
  • 4. Model View ViewModel ViewController Sencha MVVM recap
  • 5. Model View ViewModel ViewController Sencha MVVM recap Ext.data.Model Ext.Component Ext.app.ViewModel Ext.app.ViewControlle r
  • 6. Model View ViewModel ViewController Sencha MVVM recap Ext.data.Model Ext.Component Ext.app.ViewModel Ext.app.ViewControlle r View Package
  • 9. 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' }
  • 10. 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' } });
  • 11. 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 }); } });
  • 12. 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
  • 13. 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
  • 16. Save button Ext.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
  • 18. 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
  • 19. Noteworthy • Only dirty field data was sent. • Id was always sent • Same URL as read • Response data was automatically realized in view 19
  • 20. Real world data and demands
  • 21. 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' }
  • 22. 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' }
  • 23. 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' }
  • 24. 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
  • 25. Specify your own id field idProperty Consider 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' } });
  • 26. Read data from nested objects mapping Specify 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' }, ... ],
  • 27. Send all fields on save writeAllFields Proxy writer configs to ensure all fields will be sent. proxy: { type : 'ajax', url : '/companies', reader:{ type:'json' }, writer:{ type : 'json', writeAllFields : true } }
  • 28. Keep object nesting on save { _id : "57bb5d639baeb676ced2b0de", companyName : 'Ikea', address : { street : 'Storgatan 1', city : 'Stockholm', country: 'Sweden' }, updatedDate : '2016-08-23T21:26:08.358Z' }
  • 29. Keep object nesting on save expandData Makes sure the mapped field data sent back is in a nested format. nameProperty Property 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 } }
  • 31. 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' }
  • 32. dateFormat Adding the exact date format will make sure date is not altered. fields:[ ''' { name:'updatedDate', type:'date', dateFormat:'Y-m-dTH:i:s.uZ' } ],
  • 33. 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 } }
  • 34. 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 } }
  • 36. 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 }, ....... ]
  • 37. 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
  • 38. 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
  • 39. 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
  • 40. Useful? • Automatically created stores. Company model function licenses() will return accociated licenses. var viewModel = this.getViewModel(), companyProfile = viewModel.get('companyProfile'), store = companyProfile.licenses();
  • 41. Useful? • Automatically created stores. Company model function licenses() will return accociated licenses. • License function getCompany() will return Company model. varviewModel = this.getViewModel(), companyProfile = viewModel.get('licenses'), store = companyProfile.licenses(), firstLicense = store.first(), console.log(firstCompany.getCompany()); // Returns companyProfile
  • 42. 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'} ] }
  • 43. • Inline associations Licence 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
  • 44. 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
  • 45. 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
  • 46. 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
  • 47. Associated store data is not realized on save. Live example 47
  • 48. 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
  • 49. 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 }); }
  • 50. 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 }); }
  • 51. 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
  • 52. What happens if license array is missing? Demo! 52
  • 53. 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
  • 54. Proxy/Remote associations Ext.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.
  • 55. Proxy/Remote associations Ext.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
  • 56. 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
  • 57. 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
  • 59. 59
  • 60. 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
  • 61. View with multiple models 61 Company Licenses Pool cars Feedback
  • 62. View with multiple models 62 Company Licenses Pool cars Feedback Data model + association
  • 63. View with multiple models 63 Company Licenses Pool cars Feedback Data model + association Store
  • 64. View with multiple models 64 Company Licenses Pool cars Feedback Data model + association Store Data model
  • 65. • 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
  • 66. One point save onSave:function(){ if(this.getSession().getChanges()){ this.getSession().getSaveBatch().start(); } },
  • 67. 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
  • 68. Enable session var store = this.getViewModel().getStore('cars'); store.setSession(this.getSession()); • Enable session in view • Add stores to session
  • 69. 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
  • 70. 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
  • 73. 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
  • 74. 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
  • 78. Handle error response { "IsSuccess": false, "ErrorMessage": "Missing company" }Error returned from the server in a json response when logic fails or data is missing.
  • 79. 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.
  • 80. 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
  • 82. 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

Editor's Notes

  • #4: Its easy to write applications that are simple. You decide everything
  • #5: Refesh our memories
  • #8: The world smallest CRM system
  • #9: Beutiful application
  • #13: Binding has given us so mych power
  • #14: Create the actual view package
  • #21: Lets add some real world
  • #29: So common. Object/no sql
  • #32: Dates are from hell. I hate dates. with all my heart
  • #36: Most data Associate . Associations enable you to express relationships between different Ext.data.Model
  • #37: Our product owner demands a grid with licenses
  • #38: In most databases you reference using a "foreign key"
  • #44: Talk about different demands. Proxy is preffered
  • #73: This is a VERY common demand.
  • #79: Errors are standardized thrue the backend