A presentation i gave at JS-IL conference about building a SPA (single page application) using Durandal and other supporting libraries (Require.JS, Knockout and Q)
4. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
Web app that fits on a single web page
providing a fluid UX by loading all
necessary code with a single page load
5. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
Navigation, history, deep linking
Persisting state
Initially loading most of its content
Download additional features as needed
11. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
Stands for Model-View-ViewModel
Not technology specific
Awesome with data binding!
MVVM is, foremost, a separation pattern
14. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
Observables are special JavaScript
objects that can notify subscribers about
changes, and can automatically detect
dependencies.
16. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
<div class="console-brief" title="Go to console details">
<img data-bind="attr: { src: consoleImageName }" class="img-
polaroid"/>
<address data-bind="text:Title"></address> By <span data-
bind="text: Manufactorer"></span><br />
….
</div >
var Title = ko.observable();
17. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
Notifies when items are added/removed
DOESN’T notify when object are changed
Compatible with standard array functions
Tracks the state of the array
18. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
define(['services/dataservice'], function
(dataservice) {
var games = ko.observableArray();
dataservice.getGamesPartials(games);
var vm = {
games: games,
};
});
20. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
Based on other properties and observables
Supports data binding
Enables creation of new observables
26. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
Dependency injection for JavaScript
Load only what we need, when we need
Uses the AMD pattern
Break your applications into smaller,
more manageable, units of code
27. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
Module
F
Module
E
Module
A
Module
B
Module
D
Module
C
28. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
Module
F
Module
E
Module
A
Module
B
Module
D
Module
C
32. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
Loading require.js
Define the module
Each dependency has a
corresponding object
No more messy script tags parade
Load only what's needed, WHEN needed
Allows for nested dependencies
42. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
Configure the routes
Activate the Router object
Bind away!
43. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
Based on the popular SammyJS framework
A singleton module – only one per app
Multiple ways to define routes
Mapping is done most to least specific
44. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
var router =
require('durandal/plugins/router');
router.mapRoute('consoles',
'viewmodels/consoles', 'Consoles', true);
router.mapNav('games', 'viewmodels/games',
'Games');
Requires the
router object
URL
Module Name Visible
Same as mapRoute,
but always visible.
46. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
define(['durandal/system',
'services/logger','durandal/plugins/router','config','services/datacon
text'],
function (system, logger,router,config,datacontext) {
var shell = {
activate: activate,
router: router
};
return shell;
function activate() {
return
datacontext.primeData().then(boot).fail(failedInitialization);
}
function boot() {
router.map(config.routes);
return router.activate(config.startModule);
}
});
47. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
<div class="navbar-inner navbar-secondary">
<div class="btn-group" data-
bind="foreach: router.visibleRoutes">
<a data-bind="attr: { href: hash }, css:
{ active: isActive }, html: caption"
class="btn btn-info"></a>
</div>
</div>
For each visible route…
Bind the route link
Check if link is active, if
so add css class ‘active’
And its html to the
content of the link
54. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
No consistency in callback APIs
No guarantees whatsoever
Tying callbacks kills the flow of our code
55. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
A Promise represents the result of a
task, which may or may not have
completed.
By using promises we wont be calling a
passed callback, but instead – return a
promise.
56. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
getGamesForConsole("xbox360", function (err, result) {
getGamesByGenre("action", function (Err, result) {
// do more stuff here
});
});
getGamesForConsle("xbox360").then(function (result) {
return getGameByGenre(result, "action");
}).fail(failFunction);
57. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
Only one success or failure will be called
Handles will always be called asyncly
Promises can be easily chained
58. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
Pure JavaScript library, 8.5kb minified
Durandal make use of Q for its promises
Make it easy to write promise based code
Allows to wrap non promise based code
59. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
var primeData = function () {
return Q.all([getLookups(), getSpeakersPartials(null, true)]);
}
function getLookups() {
return EntityQuery.from('Lookups').using(manager).execute()
.fail(queryFailed);
}
60. Israel JavaScript Conference | 03 – 6325707 | info@e4d.co.il | www.js-il.com |
Durandal takes care of all the plumbing of
a SPA so you wont have to.
Works in a modular way, saves bandwidth
Uses KnockoutJS for its data binding
Fun!