LaceySnr.com - Salesforce Development Posts by Matt Lacey

Mobile SDK and KnockoutJS Experiments

Posted: 2015-05-24

As the lack of posts over the last month probably suggests, it's been something of a busy period for me, with a particular highlight being the Salesforce MVP Summit. For me it's not even about the content (which is always fascinating) but really the inspiration to be gained from talking with so many amazing people. It's a group of caring people that never fail to amaze me, and I'm humbled to spend time with them.

Summit aside, I've spent a large part of the month playing around and experimenting with the latest versions of the Salesforce Mobile SDK, which has advanced in leaps and bounds over the last year.

Sync Me

One of the major additions to the SDK over the last couple of years is the SmartSync Data Framework which removes the need for a developer to bother themseles with moving data explicitly via the REST API. Until quite recently the SDK had features such as this enabled in some places but not in others (i.e. for the various platform, native/hybrid/remote hybrid combinations), and with the release of version 3.1 this was all brought together into a unified architecture.

Now with 3.2 (and some more exciting changes coming in 3.3) syncing information and working offline is a breeze, there's a new "Canonical Sample App" that demonstrates how to quickly build a simple app with offline editing support using standard HTML 5 and Web Components via Polymer. If you've not checked this stuff out, then do yourself a favour and have a read of this blog post.

More KnockoutJS

The web components approach offers some serious performance, but for one of our projects I don't need any offline support, and want to a build a fairly large, single page application; that is an application that's built into one web page, though it consists of several views itself. I've spent a lot of time playing with KnockoutJS before now and really like it, but I always found it harder to use in larger applications.

These problems have largely been solved by KnockoutJS Components which were introduced in August of last year. Steve Sanderson, the creator of KnockoutJS has published a recording of a conference talk where he discusses the creation of larger applications using these new components, and I found it to be a very elegant solution.

from .NDC Conferences

The Current Experiment

I wanted to leverage these techniques within a Visualforce page on the platform, as I've discussed in the past how easy it is to use KnockoutJS with remoting to build dynamic interfaces that are better suited to mobile than straight-up Visualforce.

I used the Yeoman generator from the video above, then after each edit use gulp to build the main Javascript components and CSS into single files as they would be packaged in any other environment, and load those files into a static resource. These are then included in a simple Visualforce page that reflects the index.html generated by gulp:

<apex:page showHeader="false" sidebar="false" docType="html-5.0" standardStylesheets="false" applyBodyTag="false" applyHtmlTag="false">
   <head>
     <meta charset="utf-8"/>
     <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
     <title>My App</title>
     <link rel="stylesheet" href="{!URLFOR($Resource.TheApp, 'css.css')}"/>
     <script src="{!URLFOR($Resource.TheApp, 'scripts.js')}"></script>
   </head>

   <body data-spy="scroll" data-target=".pageNav" data-offset="100">
     <div id="page" class="container"
 data-bind="component: { name: route().page, params: route }"></div>
     <c:about/>  
     <nav-bar params="route: route"></nav-bar>
   </body>
</apex:page>

In the architecture described by Steve Sanderson the About page is stored as a KnockoutJS component in the file hierarchy, and includes a JS controller file and a corresponding HTML template. In order to leverage the platform I wanted to see if I could use a Visualforce component to the same effect, and this does indeed work quite nicely. In the page source above you might have noticed the <c:about/> tag, and the source for that looks like this:

<apex:component>
    <script>
        define('about', ["knockout"], function(ko)
        {
            function AboutViewModel(params)
            {
                var self = this;

                this.message = ko.observable("Some message");</pre>

                self.doSomething = function()
                {
                    self.message('You clicked!');
                };
            }

            return {
                viewModel: AboutViewModel,
                template: {element: "aboutTemplate"}
            };
        });
    </script>
    <template id="aboutTemplate">
        <h2>This is a VF Component</h2>
        <span data-bind="text: message"></span>

        <button data-bind='click: doSomething'>Click me</button>
    </template>
</apex:component>

Not rocket science, and not doing anything majorly useful yet, but it does provide a nice platform-friendly way of managing the parts of a single page app without having to constantly upload and refresh static resources.

Clearly there's some more learning to be done as to whether this will really prove to be a viable option, and I'll write more as I go, but I hope this gets others thinking about the possibilities of combining native platform features with other frameworks to build re-usable components that can be shared between differenent single page applications. In the mean time I'd be very interested to hear of other approaches people have taken to build this kind of solution.

Related Posts