Corrado's Blog 2.0

Online thoughts of a technology funatic

MvvmStack for WinJS Part #3

In this 3rd episode of the MvvmStack saga I’m going to describe how to use the set of core mvvm modules we saw in previous posts describing application dependent modules.

image

Let’s start describing navigationTargets.js

(function (winjs) {
    "use strict";

    winjs.Namespace.define("Demo.Navigation", {
        target: {
            home: "/pages/home/home.html",
            section: "/pages/section/section.html",
            noConnectivity: "/pages/noconnectivity/noconnectivity.html"
        }
    });
    
}(WinJS))

It’s a simple object, nested into Demo.Navigation namespace (use your own namespace in production code) that exposes a set of uri pointing to application pages, this allows us to centralize pages uri and pass these infos to various modules. As soon as you add new pages this object must be updated with new properties.

applicationController.js represents an optional application object shared among viewmodels, it can be used as a general data cache and it’s also persisted during suspend/resume events.

(function (winjs,mvvmStack) {
    "use strict";

    var ApplicationController = WinJS.Class.derive(mvvmStack.ApplicationControllerBase,null,
        {
            selectedHomeSection: 0,
            serialize: function () {
                return {
                    selectedHomeSection: this.selectedHomeSection
                };
            },
            hydrate: function (applicationState) {
                this.selectedHomeSection = applicationState.selectedHomeSection;
            }
        });

    var applicationController = new ApplicationController;

    winjs.Namespace.define("Demo.Application", {
        ApplicationController: applicationController
    });

})(WinJS,MvvmStack)

As you see in previous code, the object inherits from ApplicatioControllerBase class and exposes a selectedHomeSection that is used by homepageViewModel to inform sectionViewModel about what section has been selected by the user.

serialize and hydrate are functions invoked by persistence service when object must be persisted and lately rehydrated.

ApplicationController class is nested inside Demo.Application namespace.

networkService.js

While not mandatory, it is a service that monitors network connection status and using messenger object it posts messages when network connectivity status changes. The message is subscribed and handled inside connectivityService.js module

(function (winjs, messenger) {

    var _networkInfo = Windows.Networking.Connectivity.NetworkInformation;
    _networkInfo.addEventListener("networkstatuschanged", onNetworkStatusChange);
    var notifiedStatus = isInternetAvailable();

    //Handles network status changes
    function onNetworkStatusChange() {
        var mes = messenger.networkStatusChanged();
        mes.isInternetAvailable = isInternetAvailable();
        if (mes.isInternetAvailable != notifiedStatus) {
            notifiedStatus = mes.isInternetAvailable;
            messenger.send(mes);
        }
    }

    //Gets a value indicating whether internet connection is available
    function isInternetAvailable() {
        var connectivityLevel = Windows.Networking.Connectivity.NetworkConnectivityLevel.none;
        var profile = _networkInfo.getInternetConnectionProfile();
        if (profile != null) connectivityLevel = _networkInfo.getInternetConnectionProfile().getNetworkConnectivityLevel();
        return connectivityLevel === Windows.Networking.Connectivity.NetworkConnectivityLevel.internetAccess;
    }

    winjs.Namespace.define("Demo.Application.Services.Network", {
        isInternetAvailable: isInternetAvailable
    });

})(WinJS, Demo.Application.Messenger)

connectivityService.js is a completely optional component that in the demo application handles connectivity changes messages navigating to a static noConnectivity.html pagecontrol. Your application can freely ignore this module and handle connectivity changes in a total different way, all you need to do is to subscribe the message as connectivityService does.

viewModelLocator.js takes care of creating the viewModels associated with application pages, it’s a class that derives from viewModelLocator base and overrides createViewModelForUrl function.

createViewModelForUrl is the core function that take care of creating a viewModel before page gets loaded, depending on target url.

 createViewModelForUrl: function (uri) {
                switch (uri) {
                    case target.home:
                        this.viewModels.homeViewModel = this.viewModels.homeViewModel || new Demo.ViewModels.HomeViewModel(applicationController);
                        break;
                    case target.section:
                        this.viewModels.sectionViewModel = new Demo.ViewModels.SectionViewModel(applicationController, services.imageService);
                        this.viewModels.sectionViewModel.load();
                        break;
                }
            },

The snippet demonstrates how a single instance viewModel is creates for home page, while when user navigates to section page, a SectionViewModel instance is instantiated and related images loaded.

Since each viewModel becomes a property of viewModels object, when a new ViewModel is added the object must be updated adding a property that matches ViewModel name.

this.viewModels = {
            homeViewModel: null,
            sectionViewModel: null
        };

Note: I’m sure code can be refactored to avoid this step, maybe in a future release… Smile

The code also includes a createDesignTimeViewModels function, I’ll describe it in a forthcoming post regarding Blendability.

Closing

In next post we’ll analyze pages ViewModels, how to create and pair them with related View.

No Responses to “MvvmStack for WinJS Part #3”

RSS feed for comments on this post. TrackBack URL

Leave a Response