Sunday, March 22, 2015

Mobile Design Template and Angular.JS

Problem

We had implemented a multi-step wizard for our client.  Two of the requirements for this wizard was that it needed to be mobile-friendly, and it needs to have bilingual support.  To meet this requirement I had tried to implement a mobile version of the wizard using Mobile Design Templates.   I had previously built a simple mobile-friendly Visualforce page using Mobile Design Templates and Underscore.JS following the Getting Started with Mobile Design Templates blog post from Salesforce.

Given the complexity of this application, I had used Angular.JS as the back-end.  However, I ran into trouble when I tried to incorporate the Mobile Design Templates' toggle input into this application.

We had this picklist field with two values that we want to render as a toggle input.  To do so I had the Angular.JS controller called the service that would grab the labels for those two values from Salesforce, in order to meet the bilingual requirement, and set those label as data-on-label and data-off-label.

(function() {

var app = angular.module('app', []);



 app.controller('InputCtrl', function InputCtrl(InputLabelService) {

        var inputScope = this;



        // Get the label of the input form from Salesforce
        InputLabelService.getFormValues().then(
            function(picklists) {
                inputScope. inputLabels = picklists. inputLabels;


               // This renders the toggle input
               $(document).trigger('onTemplateReady');
        });
    });
})();



<section class="border-bottom">
    <div class="content">
    <h3>Input</h3>
        <div class="form-control-group">
            <div class="form-control form-control-toggle" data-on-label="{{inputLabels[0]}}" data-off-label="{{inputLabels[1]}}">
                <input type="checkbox" name="toggle">
             </div>
         </div>
     </div>
 </section>
The problem was that Mobile Design Templates render data-on-label and data-off-label on the toggle input upon the call to 'onTemplateReady' Javascript trigger.  However, because how the two-way binding of Angular.JS is done, the rendering of the toggle input is done before Angular.JS can set the data-on-label and data-off-label with appropriate values, which ended up rendering the toggle input without any label.

Solution

The way I had gotten around this issue was by putting a $watch listener on the inputLabels and to trigger 'onTemplateReady' when it has a new value.

(function() {

var app = angular.module('app', []);



 app.controller('InputCtrl', function InputCtrl(InputLabelService) {

        // Get the label of the input form from Salesforce
        InputLabelService.getFormValues().then(
            function(picklists) {
                $scope.inputLabels = picklists.inputLabels;



                $scope.$watch('inputLabels', function(newVal, oldVal) {



                    if (newVal) {

                       // This renders the toggle input
                       $(document).trigger('onTemplateReady');
                   }
               });
        });
    });
})();




Takeaway

In the end, I actually ended up not using Mobile Design Templates as the tabbed navigation, which I had used in one of the page, didn't work in iPhone.  Instead, I ended up using Bootstrap along with Angular.JS.  I still think Mobile Design Templates is a good tool to have in your tool belt if you are building a very simple mobile application on Salesforce1; however, for any application with a moderate complexity, I would definitely look at alternative, such as Bootstrap I have used for this project or Ionic Framework.

4 comments: