Ext JS Architecture Best Practices Mitchell Simoens Senior Software Engineer, Sencha [email protected] @LikelyMitch
Ext JS Architecture Best Practices
Mitchell SimoensSenior Software Engineer, Sencha
[email protected]@LikelyMitch
Let’s Start Coding!So excited to start coding the new project! Wait!!!!
Planning
• Feature list you get is a high level list.- As a developer, you have to create a technical list.
• Plan your namespaces.- Features are a great namespace outline.
- Sections may be namespacable.
- Don’t be afraid to subclass.
• Use view controllers instead of global controllers, where possible.
• Don’t forget about the router!
3
Namespacing
Sample Portal Namespaces
Portal.view.main.Main (Cmd generated)Portal.view.main.Center
Portal.view.header.Container
Portal.view.user.login.Form
Sample Fiddle Namespaces
Fiddle.view.main.Main (Cmd generated)Fiddle.view.main.CenterFiddle.view.main.Menu
Fiddle.view.header.ContainerFiddle.view.header.TitleFiddle.view.header.Framework
Fiddle.view.user.login.FormFiddle.view.user.login.WindowFiddle.view.user.HeaderFiddle.view.user.MenuFiddle.view.user.Settings
Fiddle.view.file.TreeFiddle.view.file.Menu
Fiddle.view.editor.ContainerFiddle.view.editor.item.ItemFiddle.view.editor.item.DataFiddle.view.editor.item.Direct
Fiddle.view.search.ContainerFiddle.view.search.FormFiddle.view.search.Results
Code Reuse
Means of Code Reuse
• Subclassing/Abstracts- Great for common UIs (think grids).
• Plugin- Share common functionality with different components. Methods/configs not on class prototype.
• Mixin- Not used much in apps. Like plugins but applies methods/configs onto the class prototype.
• Singleton- Great for logic extraction.
• Cmd Package- Share among many apps, can have any of the above.
MVC vs MVVM
MVC vs MVVMWhich to use and why?• Debate is only on which controller to use really.
• Debate is really not a valid debate.
• Use them both! Depends on the need.- Ext.app.Controller is global.
• Since ViewController was created, Controller shouldn’t listen to user interactions.
- Ext.app.ViewController is local.
• Think views as widgets.
• Shouldn’t know about anything other than the view it’s attached to.
Controller/ViewController Communication
// don’t do thisvar controller = MyApp.app.getController(‘Foo’);controller.doSomething();----------// do this insteadthis.fireEvent(‘didsomething’, this);
// in other controllerlisten : { controller : { ‘*’ : { didsomething : ‘doSomething’ } }}
// or use global eventsExt.fireEvent(‘didsomething’, this);
// in other controllerlisten : { global : { didsomething : ‘doSomething’ }}
// orExt.on(‘didsomething’, function() {});
Router
RouterPlan to use it before it’s too late!• Allows the browser’s back/forward button to navigate in your app.
- Do not undervalue this!
• Allows deep linkage into your app.- Do not undervalue this!
- Bookmark or email a link.
• Let routes do the work, not the view listeners.- Become route centric!
• Can be hard to refactor at the end to support routes. Support it at the beginning.
onItemDblClick : function(gridview, record) { this.redirectTo(‘user/’ + record.getId());}
routes : { ’user:id’ : { action : ‘onUser’, conditions : { //make id optional but only digits ‘:id’ : ‘(?:(?:\/){1}(\d+))?’ } }},onUser : function(id) { if (!this.hasUserGrid()) { this.showUserGrid(); } if (id) { this.showUserForm(id); } else if (this.hasUserForm()) { this.destroyUserForm(); }}
Route Centricity
• Use redirectTo more instead of doing the thing in the event listener.
• Requires a change of thought.
• Reaction to a user interaction is more async.
To Config or Not To Config
config : { userId : null},
applyUserId : function(id) { return parseInt(id);},
updateUserId : function(id) { Ext.Ajax.request({ url : ‘/user’, params : { id : id }, scope : this, success : this.onUserLoad, failure : this.onUserFail });}
Configs
• Use the getter and setter, not the actual property
• Use applier to transform and sanitize the value *if needed
• Use updater to react to value changes- Use this to make your class dynamic
Route Reaction
onUser : function(id) { if (!this.hasUserGrid()) { this.showUserGrid(); } if (id) { this.showUserForm(id); } else if (this.hasUserForm()) { this.destroyUserForm(); }}
showUserForm : function(id) { var form = this.getUserForm();
if (form) { form.setUserId(id); } else { this.createUserForm(id); }}
When to use a configShould everything be a config?• Sure
• There is a cost to generating the getter/setter
• There is a cost when initConfig is called
• Weigh the need with the cost- Your class can be more dynamic and reactive
• Remember to clean up!- Unless you are using Ext JS 6.2.0+ (thank you reaper!)