Why mini-spa/hybrid-spa? Let’s see the pictorial difference
between a traditional page lifecycle and a SPA (Single Page Applications) lifecycle –
One of the key benefit I see in following the SPA design
principles for developing rich, complex web applications is the “stateful”ness
we get [HTTP being stateless protocol by nature is one of the biggest
disadvantage we know it is for building web apps vs say native apps.]. For
complex web apps, it may be too idealistic to have just one “full” initial http
request to get a page, and then subsequent async calls to load further pages or
data. However, we can do it module-wise i.e. certain parts of the web app follow SPA design, others may or may not follow SPA design.
This is referred to as mini-spa or hybrid spa.
Using AngularJs framework, I've come up with a sample
application which follows SPA design principles. I’m using angular route module ngRoute along with angular directive ngView to define routes –
controller & view associated with each route. It is essentially MVC pattern
on the client-side. Moreover, our app is now route-driven on client-side. [The browser
back and fro buttons are supported]
In the sample web app, we have two modules – music (music albums) and
movies (movie dvds). In each module, user can filter results and view/edit the record. [NOTE: using mvc music store
database from codeplex. Source]
For each module, I've defined corresponding angular module -
- ngModule musicAlbumsApp for music module
- ngModule movieDvdsApp for movie module
The route configuration for music module is as follows –
(function (app) {
var routeConfig = function ($routeProvider) {
$routeProvider.when("/", {
controller: "musicAlbumListController",
templateUrl: window.miniSpaApp.rootUrl
+ "MusicAlbums/List",
reloadOnSearch: false
}).when("/:genreId", {
controller: "musicAlbumListController",
templateUrl:
window.miniSpaApp.rootUrl + "MusicAlbums/List",
reloadOnSearch: false
}).when("/Detail/:id", {
controller: "musicAlbumDetailController",
templateUrl:
window.miniSpaApp.rootUrl + "MusicAlbums/Detail",
reloadOnSearch: false
}).when("/Edit/:id", {
controller: "musicAlbumEditController",
templateUrl:
window.miniSpaApp.rootUrl + "MusicAlbums/Edit",
reloadOnSearch: false
}).otherwise({ redirectTo: "/" });
};
routeConfig.$inject = ['$routeProvider'];
app.config(routeConfig);
})(angular.module("musicAlbumsApp"));
Each route maps to an angular controller
and a view/template.
In our main page (MusicAlbums - Index View), we
include the angular scripts and define our container div using ngView directive
to load different views, as follows –
@section
HeadContent
{
@Scripts.Render("~/bundles/angularMusicAlbums")
}
<div data-ng-app="musicAlbumsApp" data-ng-view="" data-ng-cloak="">
</div>
Similarly, for movie module we've defined it's route configuration and container div using ngView directive.
Complete sample application is
located here.