Starting your application on the right foot is important. You’re probably excited to start coding, but it’s important to think about the architecture you’ll need. In this session, we’ll cover architectural best practices including the difference between MVC and MVVM, how to start architecting your application, and using the Ext JS router to your advantage.
3. 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
10. 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.
12. MVC vs MVVM
Which 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.
13. Controller/ViewController Communication
// don’t do this
var controller = MyApp.app.getController(‘Foo’);
controller.doSomething();
----------
// do this instead
this.fireEvent(‘didsomething’, this);
// in other controller
listen : {
controller : {
‘*’ : {
didsomething : ‘doSomething’
}
}
}
// or use global events
Ext.fireEvent(‘didsomething’, this);
// in other controller
listen : {
global : {
didsomething : ‘doSomething’
}
}
// or
Ext.on(‘didsomething’, function() {});
15. Router
Plan 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.
16. 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.
18. 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
19. 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);
}
}
20. When to use a config
Should 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!)
Notas del editor
Creating an initial plan on the classes you will need based on the features and design is important. It’s like a database; you would just start creating tables without some thought on what columns you need in certain tables and what tables are going to be joined together. An initial plan doesn’t have to be a final plan but it’s at least something to start on.
May be hard to see but the entire page is wrapped in a red border, this region is the “main” region. You may also call it the viewport but that can mean other things so I like to stick with main.
A common UI is a header up top with a company’s logo and maybe the company name or other information. On a login screen like this, likely to be blank but depends on your app.
Under the header you have the rest of the app, I call this the center region. I name it this way as I use border layout a lot so it fits with that layout’s terminology.
So now you have two main sections of your UI. You can now start to break them down more. In this view, the header doesn’t have anything else but the center has a login section. You are now breaking the UI up into individual modules or widgets.
From the last slide, here are some namespaces I can go with. Very simplistic on that slide so we need to look at something a bit more complex like the screen you see after you login.
This is Sencha Fiddle 2 and it may be very hard to see but I’ve started to draw boxes around sections of the application. This allows me to visually start to see the separate sections in a way that I can plan my namespacing.
However, namespacing doesn’t necessarily need to follow the sections. For example, in the top right there is a section for the user info where you can click to login or if already logged in shows the username and when clicked will show a user menu. This is in the header but there is likely other user features such as a settings form. I have to decide if the namespace should go under the header section namespace or the user feature namespace. I tend to favor namespacing by feature than section if there is a conflict but nothing wrong with having that user section under the header namespace.
A bit more thought out namespacing scheme. More classes will no doubt be needed but you can start seeing certain namespaces will encapsulate certain things.
This one is important. Ext JS’ class system allows great extensibility which gives you flexibility into your code designs. One thought is the more code you can reuse the better.
There are many ways to reuse code and there really isn’t a silver bullet answer; this will depend on the independent thing at hand.
I get asked this question a lot, “Should I use MVC or MVVM?” Well, since I’m sure you have already started to think out what classes you’ll need, you tell me!
You see, the question really isn’t which one should you use, it’s really which controller should you use and it’s not a valid debate. Why not use both if your application needs to? I primarily use view controllers as it allows me to think in smaller pieces, my views become widgets. However, there are certain global aspects of applications so a global controller still has it’s uses.
Let me give you an example. Sencha Fiddle has many views such as a file tree and an editor tab panel. When you interact with those, a view controller can react and do things. But if you have an editor focused and you press control + s (meaning save the fiddle), that save is a global thing. So I have local and global needs in Fiddle so I use both MVC and MVVM, it’s not black or white.
However, when you use both controllers you can get trapped into tightly coupling logic to the current state of your application.
So what if down the development line you have to change something or the name of a controller no longer fits what it does so you want to rename it. If you are looking up individual controllers, you now have to go through your app looking for these lookups and update that code which will eventually bite you and cause regressions.
Instead, use events either on the controller event domain or Ext JS’ global event system so your controller (or whatever) fires an event and doesn’t care about anything else. Other controller can then listen to these events and react for their uses. Now, your code execution is much more flexible and fluid.
Ever since Ext JS 5 we have had a router and it’s an often overlooked feature. I’m the kind of web developer that I’ll watch people use their browser. I still see lots of people using the browser’s back and forward buttons and they expect whatever they are on to work as they expect. A web application should and can work like a normal multipage site.
Say you have a grid and when a user double clicks on a grid row you want to open a form to edit that row or you want to see details about it. You’ll still add an itemdblclick listener but instead of that listener opening the view, it simply calls redirectTo to change the hash in the browser’s address bar. It’s like I discussed with controllers, it does one thing and doesn’t know about anything that happens after.
You then setup a route to listen to this hash and the route then takes care of opening that view. Here’s the tricky part about it, you have to think about when someone is first loading the application with that route. Depending on your application, you may want to still show the grid and the view so you have to see if the grid is instantiated and if not then show the grid. And then handle if there was an id passed.