Create the ToDoList Sample App

In Visual Studio 2013, the Cordova tools are released as a preview (CTP) version. Cordova tools will be released as part of Visual Studio 2015 and we recommend that you now use Visual Studio 2015 RC to develop apps using Visual Studio Tools for Apache Cordova. You can download Visual Studio from the Microsoft Download Center.

In this tutorial, you’ll learn how to create a task list sample app using AngularJS (AngularJSToDo). This app allows users to create new tasks, check them off, and remove them. The app also stores tasks using HTML5 Web Storage on the device. (The complete sample uses Microsoft Azure Mobile Services to store data, and also uses Bing Maps to provide valid addresses.) This sample uses JavaScript code, but you can also write your Cordova app in TypeScript.

Note

For an overview of tasks required to build a Cordova app, see Create Your First Apache Cordova App.

The task list sample app is available for multiple frameworks, and can be downloaded here:

To download ToDoList samples for Visual Studio 2013, see the deprecated samples on github.

To download other samples for Visual Studio Tools for Apache Cordova that demonstrate multi-page navigation and other features, see the Ionic SideMenu Starter Template, AngularJS Master-Detail Page sample, and WinJS Navigation App template. Visual Studio 2013 versions of these samples are here and here.

In this tutorial, you’ll follow these steps:

  1. Create a project

  2. Create the UI

  3. Add the AngularJS framework

  4. Register app modules

  5. Add the data model

  6. Add the view logic and data binding

  7. Build and run the ToDo List app

  8. Add Bing Maps services

  9. Add Azure Mobile Services

Pre-requisites

Before you can create a new project, make sure that you’ve met all system requirements and installed the Visual Studio Tools for Apache Cordova extension for Visual Studio. For more information, see Install Visual Studio Tools for Apache Cordova.

Create a project

Create a new Cordova project in Visual Studio by following the steps described in Create Your First Apache Cordova App. Alternatively, start with a new blank app by choosing File, New, and then Project in Visual Studio. In the New Project dialog box, choose Installed, Templates, JavaScript, Apache Cordova Apps, and then choose the Blank App template.

Create the UI

The main UI in the task list sample app consists of the following elements:

  • An <input> element for new list items.

  • An AngularJS template that will display each task in the task list.

The <input> element looks like this:

<input id="new-todo" placeholder="What needs to be done?" ng-text-change="addToDo()" ng-model="newToDoText" autofocus>

When you first run the app, some of the attributes in the preceding code won't do anything. For example, the AngularJS ng-model directive enables two-way data binding, and allows you to save the entered task when the addToDo() function runs.

For the task list, we define a template using some nested <div> elements that wrap several other elements. For example, the nested <input> element shown here is used to display each task string.

<div class="templateWrapper" ng-repeat="toDoItem in todos">
    <div class="templateContainer">
        <input class="templateTitle" ng-class="{crossedOut: toDoItem.done}" type="text" ng-text-change="changeToDoText(toDoItem)" ng-model="toDoItem.text" />
        <!-- More list item HTML elements -->
    </div>
</div>

In the preceding code, the AngularJS attribute, ng-repeat, allows you to define the top <div> element as a template to display task list items. Later, when you attach actual data and run the app, ng-repeat will add the child <div> element (templateContainer) and its child elements to the DOM for each stored task list item.

Note

Because Cordova is not dependent on any particular JavaScript framework, we are not trying to provide in-depth information about AngularJS programming in these steps. Instead, we are showing a good example of one way to create a cross-platform app using Visual Studio Tools for Apache Cordova.

Now, we will add the complete markup for index.html.

Add markup for the list

  • Open index.html, and replace the <body> element with the following code.

    <body ng-app="xPlat">
        <section id="todoapp" ng-controller="ToDoCtrl">
            <header id="header">
                <div id="headerBand"></div>
                <input id="new-todo" placeholder="What needs to be done?" ng-text-change="addToDo()" ng-model="newToDoText" autofocus>
            </header>
            <section id="main">
                <div id="todo-list">
                    <div class="templateWrapper" ng-repeat="toDoItem in todos">
                        <div class="templateContainer">
                            <input class="templateTitle" ng-class="{crossedOut: toDoItem.done}" type="text" ng-text-change="changeToDoText(toDoItem)" ng-model="toDoItem.text" />
                            <h3 class="templateAddress">{{toDoItem.address}}</h3>
                            <button class="templateLeft templateToggle" ng-class="{'checked': toDoItem.done, 'unchecked': !toDoItem.done}" ng-mousedown="toggleToDoDone(toDoItem)"></button>
                            <button class="templateLeft templateRemove" ng-click="removeToDo(toDoItem)"></button>
                        </div>
                        <div class="templateBorder"></div>
                    </div>
                </div>
            </section>
        </section>
    
        <script src="scripts/index.js"></script>
    </body>
    

    When you add the AngularJS framework (in later steps), other AngularJS attributes specified in index.html will become meaningful, but for now they won't have any effect when you run the app. Here are the other AngularJS attributes included in index.html:

    • ng-app directive to specify the root node of an AngularJS app.

    • ng-controller to specify the AngularJS controller to support MVC.

    The default <body> element in the Blank App template included an Apache Cordova reference and a reference to platformOverrides.js, which you’ve overwritten. In the next step, you’ll add these references back to the file, to the <head> element.

Add the Cordova library reference

  • In index.html, add the following script references in the <head> element, before the other script references.

    <!-- Cordova reference -->
    <script src="cordova.js"></script>
    <script src="scripts/platformOverrides.js"></script>
    

Add CSS style information

  • In the css folder, open index.css, and add the following CSS style information for HTML elements and templates.

    /* reset layout*/
    html,
    body {
        margin: 0;
        padding: 0;
    }
    
    /* body*/
    body {
        background: #F7f7f7;
        color: #4d4d4d;
        width: 100%;
        margin: 0 auto;
    }
    
    /* no outline for buttons & checkboxes*/
    button,
    input[type="checkbox"] {
        outline: none;
    }
    
    /* section styles*/
    @media (min-width: 550px) {
        #todoapp {
            width: 74vw;
            left: 13vw;
            top: 50px;
        }
    }
    
    #todoapp {
        background: rgba(255, 255, 255, 0.9);
        border: 1px solid #ccc;
        position: relative;
        border-top-left-radius: 2px;
        border-top-right-radius: 2px;
        box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.15);
    }
    
    /* the 2 red rulers*/
    #todoapp:before {
        content: '';
        border-style: solid;
        border-left-color: rgba(242, 103, 103, 1);
        border-right-color: rgba(242, 103, 103, 1);
        border-width: 1px;
        z-index: 2;
        width: 2px;
        position: absolute;
        top: 0;
        left: 40px;
        height: 100%;
    }
    
    /* dark band on the header*/
    #headerBand {
        position: relative;
        height: 4vh;
        max-height: 20px;
        border-bottom: 1px solid #6c615c;
        background: rgba(52, 59, 69, 1);
        border-top-left-radius: 1px;
        border-top-right-radius: 1px;
    }
    
    /* the new to-do entry*/
    #new-todo {
        background: rgba(237, 237, 237, 0.9);
        position: relative;
        margin: 0;
        height: 10vh;
        max-height: 70px;
        font-size: 21px;
        font-family: "Arial";
        border: 0;
        outline: none;
        color: rgb(114, 115, 115);
        padding: 0 0 0 56px;
        width: 100%;
        box-sizing: border-box;
    }
    
    /* the main section that hosts the listview*/
    #main {
        position: relative;
        z-index: 1;
        border-top: 1px dotted #adadad;
    }
    
    /*todo list*/
    #todo-list {
        height: 86vh;
        min-height: calc(100vh - 90px);
        margin: 0px;
        overflow-y: auto;
    }
    
    /*the host template*/
    .templateWrapper {
        position: relative;
        overflow: hidden;
    }
    
    .templateBorder {
        height: 0;
        border-bottom: 2px solid #bfdbf2;
    }
    
    /* container for the todo-address div*/
    .templateContainer {
        width: calc(100% - 50px);
        margin: 4px 5px 0px 45px;
    }
    
    .templateContainer input[type="text"] {
        font-size: 18px;
        font-family: "Arial";
        background: none;
        color: #2d3239;
        border: 1px solid rgba(0, 0, 0, 0);
        line-height: 0.6em;
        margin: 0px;
        width: calc(100% - 10px);
        display: block;
        padding: 4px 0px 4px 10px;
    }
    
    .templateContainer input[type="text"]:active,
    .templateContainer input[type="text"]:focus {
        color: #2d3239;
        border: 1px solid #b2b2b2;
        outline: none;
        margin-left: 2px;
        text-decoration: none !important;
        padding-left: 8px;
    }
    
    input[type="text"]:active ~ .templateRemove,
    input[type="text"]:focus ~ .templateRemove,
    .templateRemove:active,
    .templateRemove:focus {
        display: inline-block;
    }
    
    input[type="text"]:active ~ .templateToggle,
    input[type="text"]:focus ~ .templateToggle,
    .templateRemove:active ~ .templateToggle,
    .templateRemove:focus ~ .templateToggle {
        display: none;
    }
    
    .crossedOut.templateTitle {
        text-decoration: line-through;
    }
    
    .templateContainer .templateAddress {
        color: #727272;
        font-size: 12px;
        font-family: "Arial";
        padding-top: 0px;
        margin: 0px 0px 10px 11px;
        font-weight: normal;
    }
    
    .templateContainer p {
        margin: 0px 0px 4px 0px;
    }
    
    /* checkbox on the templated item*/
    .templateLeft {
        position: absolute;
        top: 6px;
        left: 5px;
        border: none;
        width: 29px;
        height: 29px;
        min-width: 0;
        min-height: 0;
    }
    
    /* button for remove*/
    .templateRemove {
        display: none;
        background-image: url('https://go.microsoft.com/fwlink/?LinkID=403181');
    }
    
    button {
        background-color: transparent;
    }
    
    button.checked {
        background-image: url('https://go.microsoft.com/fwlink/?LinkID=403179');
    }
    
    button.unchecked {
        background-image: url('https://go.microsoft.com/fwlink/?LinkID=403180');
    }
    

You can take a look at the empty task list in one of the emulators to verify that everything looks correct. In this step, you’ll run the AngularJSToDo list app on either Windows or on the Apache Ripple emulator, which have minimal setup requirements. If you prefer to test your app on another target, see the following topics: Run Your Apache Cordova App on Android, Configure the Visual Studio Tools for Apache Cordova, and Run Your Apache Cordova App on Windows Phone.

To build and run the app

  1. Choose Windows-x64, Windows-x86, or Android from the Solution Platforms list.

  2. If you chose the Android platform, choose one of the Ripple emulators, as shown here.

    Selecting the Ripple emulator

    If you chose a Windows platform, you can run the app on the default deployment target, Local Machine.

  3. Press F5 to start debugging, or Shift+F5 to start without debugging.

    The following illustration shows an example of what the AngularJSToDo list app looks like in one of the Ripple emulators (with no actual data yet attached).

    Initial ToDo List with no data

    Tip

    If you are running on a Ripple emulator and you get an error that indicates you need to install a new version of the Android SDK, use the Android SDK Manager to install it. On Windows, SDK Manager.exe is in C:\Program Files (x86)\Android\android-sdk.

    If you see an error such as Cannot find module [modulename], see Re-installing vs-tac. If you experience other problems, see Known Issues and the FAQ.

Add the AngularJS framework to your project

Now that you’ve verified your setup, you can create the AngularJSToDo app. The app uses AngularJS to separate the view model (MVC), to provide data binding, and to support native UI for different platforms.

To add AngularJS to your project

  1. From the AngularJS website, choose Download.

    In the Download AngularJS dialog box, make sure that the minified 1.3.x version of AngularJS (the default stable version) is selected, and then choose Download to save the angular.min.js script to your computer.

  2. In the Download AngularJS dialog box, choose Browse additional modules, and download angular-resource.min.js.

  3. In the Visual Studio Solution Explorer, add a new folder under the scripts folder of the project and name it frameworks.

    Note

    You cannot add this folder while the app is running. Press Shift + F5 to stop the debugger.

  4. Open the shortcut menu for the frameworks folder, and then choose Add, Existing Item. Add the two AngularJS files from steps 1 and 2 to the project.

Update the script references

  • In index.html, add the following AngularJS references in the <head> element, after the Cordova and platformOverrides script references.

        <script src="scripts/frameworks/angular.min.js"></script>
        <script src="scripts/frameworks/angular-resource.min.js"></script>
    

    Your script references in the <head> element should now look like this.

        <script src="cordova.js"></script>
        <script src="scripts/platformOverrides.js"></script>
        <script src="scripts/frameworks/angular.min.js"></script>
        <script src="scripts/frameworks/angular-resource.min.js"></script>
    

    Note

    cordova.js needs to load before the AngularJS framework files.

  • Add script references for your AngularJS modules at the end of the <body> element. Those references should now look like this.

        <script src="scripts/index.js"></script>
        <script src="scripts/services.js"></script>
        <script src="scripts/controllers.js"></script>
        <script src="scripts/directives.js"></script>
    

Register app modules

In this section, you’ll register AngularJS app modules to help separate application concerns. Modules in this app include the data model (xPlat.services), the AngularJS controller (xPlat.controller), and AngularJS directives (xPlat.directives) to support data binding. To register the modules, use the angular.module function.

To register angular modules

  1. In Solution Explorer, open the shortcut menu for the scripts folder, and then choose Add, New Item.

  2. In the Add New Item dialog box, choose JavaScript File, and name it services.js.

  3. Repeat step 2 to add two more JavaScript files to the scripts folder:

    • controllers.js

    • directives.js

  4. Open index.js, and replace the default code with the following code.

    (function() {
        'use strict';
        angular.module('xPlat', ['xPlat.services', 'xPlat.controllers', 'xPlat.directives']);
        angular.module('xPlat.directives', []);
        angular.module('xPlat.controllers', []);
        angular.module('xPlat.services', ['ngResource']);
    })();
    

Add the data model

The data model is represented by the xPlat.services module, which you’ll implement in the services.js file. This code includes a service that provides local storage of task list items using HTML5 Web Storage (localStorage property). In this initial implementation, the app also provides placeholder code for Bing Maps services, which can be implemented fully later on. The complete sample app also uses Azure to store data.

In the following code, the app calls the factory method of the xPlat.services module to generate each data model service, such as the localStorage service. One thing to note here is the inclusion of the $q service component in the service provider function. This object enables asynchronous programming, so that you can create a promise object using $q.defer. Using the promise object, you can resolve or reject the asynchronous operation when it has completed.

To add code for the data model

  • In the scripts folder, open services.js and add the following code.

    (function () {
        'use strict';
    
        angular.module("xPlat.services")
            .factory("guidGenerator", function () {
                var generatePart = function () {
                    var guidPartNumber = (Math.random() * 0x10000) | 0;
                    return (guidPartNumber + 0x10000).toString(16).substring(1).toUpperCase();
                };
    
                return function () {
                    return generatePart()
                        + generatePart()
                        + "-"
                        + generatePart()
                        + "-"
                        + generatePart()
                        + "-"
                        + generatePart()
                        + "-"
                        + generatePart()
                        + generatePart()
                        + generatePart();
                };
            })
            .factory("localStorage", ['$q', "$window", "guidGenerator", function ($q, $window, guidGenerator) {
                var localStorageKey = "toDoItems";
    
                var loadFromStorage = function () {
                    return angular.fromJson($window.localStorage.getItem(localStorageKey)) || [];
                };
    
                var saveToStorage = function (items) {
                    $window.localStorage.setItem(localStorageKey, angular.toJson(items));
                }
    
                return {
                    getAll: function () {
                        return loadFromStorage();
                    },
    
                    create: function (text, address) {
                        var item = {
                            id: guidGenerator(),
                            text: text,
                            address: address,
                            done: false
                        }
                        var items = loadFromStorage();
                        items.push(item);
                        saveToStorage(items);
                        return $q.when(item);
                    },
    
                    update: function (item) {
                        var items = loadFromStorage();
                        for (var i = 0; i < items.length; i++) {
                            if (items[i].id === item.id) {
                                items[i] = item;
                                break;
                            }
                        }
    
                        saveToStorage(items);
                        return $q.when(item);
                    },
    
                    del: function (item) {
                        var items = loadFromStorage();
                        for (var i = 0; i < items.length; i++) {
                            if (items[i].id === item.id) {
                                items.splice(i, 1);
                                break;
                            }
                        }
    
                        saveToStorage(items);
                        return $q.when(null);
                    }
                }
            }])
    
            // To support Azure, add Azure storage service
            // code here ("azureStorage").
    
            .factory("storage", ["$injector", function ($injector) {
                // var azureService = $injector.get('azureStorage');
                // return azureService.isAvailable ? azureService : $injector.get('localStorage');
                return $injector.get('localStorage');
            }])
    
            // To support Bing maps, replace mapSimulator 
            // with map code.
            .factory('mapsSimulator', ["$rootScope", "$q", "$timeout", function(rootScope, $q, $timeout) {
    
                return {                
                    getUnknownAddress: function() {
                        var deferred = $q.defer();
    
                        $timeout(function() {
                            deferred.resolve([43.465187, -80.522372]);
                        }, 1500);
    
                        return deferred.promise;
                    }
                }
            }])
    
            .factory("cordova", ['$q', "$window", "$timeout", function ($q, $window, $timeout) {
                var deferred = $q.defer();
                var resolved = false;
    
                document.addEventListener('deviceready', function () {
                    resolved = true;
                    deferred.resolve($window.cordova);
                }, false);
    
                $timeout(function () {
                    if (!resolved && $window.cordova) {
                        deferred.resolve($window.cordova);
                    }
                });
    
                return { ready: deferred.promise };
            }]);
    })();
    

Add the app's view logic and implement data binding

In this section, you’ll implement the AngularJS controller module (xPlat.controllers) to handle view logic and manipulate the data model. The code implements declarative functions in the HTML such as addToDo, which adds a new task item to the list. In this section, you’ll also add an AngularJS directive to help implement two-way data binding.

An important aspect of this code is the use of $scope to keep the data model and the view in sync. For example, by specifying $scope.addToDo = function () {}, we make the addToDo method available for declarative binding in the view (index.html).

To add the controller

  • In the scripts folder, open controllers.js and add the following code.

    The controller name, ToDoCtrl, is also referenced by the AngularJS ng-controller directive in index.html.

    (function () {
        'use strict';
    
        angular.module("xPlat.controllers")
            .controller('ToDoCtrl', ['$scope', 'mapsSimulator', 'storage', function ($scope, mapsSimulator, storage) {
            //.controller('ToDoCtrl', ['$scope', 'storage', function ($scope, storage) {
                var refresh = function () {
                    $scope.todos = storage.getAll();
                }
    
                var getAddress = function () {
                    //return maps.getCurrentPosition()
                    //    .then(maps.getAddressFromPosition, function (error) { return error.message; });
    
                    return mapsSimulator.getUnknownAddress();
                }
    
                $scope.addToDo = function () {
                    var text = $scope.newToDoText;
                    if (!text) {
                        return;
                    };
    
                    $scope.newToDoText = '';
                    getAddress().then(
                        function (address) {
                            return storage.create(text, address);
                        },
                        function (errorMessage) { return storage.create(text, errorMessage); })
                    .then(function (todo) {
                        $scope.todos.push(todo);
                    });
                }
    
                $scope.changeToDoText = function (toDoItem) {
                    getAddress().then(function (address) {
                        toDoItem.address = address;
                        return storage.update(toDoItem);
                    }, function (errorMessage) {
                        toDoItem.address = errorMessage;
                        return storage.update(toDoItem);
                    });
                }
    
                $scope.toggleToDoDone = function (toDoItem) {
                    toDoItem.done = !toDoItem.done;
                    storage.update(toDoItem);
                }
    
                $scope.removeToDo = function (toDoItem) {
                    storage.del(toDoItem).then(function (todo) {
                        var index = $scope.todos.indexOf(todo);
                        $scope.todos.splice(index, 1);
                    });
                }
                refresh();
            }]);
    })();
    

Next, you’ll implement the directives module. In this code, you’ll create a custom directive to specify behavior for the onchange DOM event. At runtime, this code associates the correct event handler (declared in HTML markup in index.html) with the element, either the addToDoText or changeToDoText functions. These are implemented in controllers.js.

To add a directive for data binding

  • In the scripts folder, open directives.js and add the following code.

    (function () {
        'use strict';
        angular.module('xPlat.directives')
            .directive('ngTextChange', function () {
                return {
                    restrict: 'A',
                    replace: 'ngModel',
                    link: function (scope, element, attr) {
                        element.on('change', function () {
                            scope.$apply(function () {
                                scope.$eval(attr.ngTextChange);
                            });
                        });
                    }
                };
            });
    })();
    

Build and run your app

In this step, you’ll run the AngularJSToDo list app on either Windows or on the Apache Ripple emulator.

To build and run the app

  • Press F5 to run the app on the same target you specified previously. Windows and the Ripple Emulator have minimal setup requirements, so we recommend initially targeting one of these two platforms.

    The following illustration shows an example of what the AngularJSToDo list app looks like in one of the Ripple emulators.

    Running the ToDo List app on Ripple Emulator

Add Bing Maps services

The complete sample includes a Bing Maps service to associate your current address with each task list item.

To add Bing Maps support to the app:

  1. In controllers.js, replace the getAddress function in with the following code from the complete sample.

    var getAddress = function() {
        return maps.getCurrentPosition()
            .then(maps.getAddressFromPosition,
             function(error) { return error.message; });
    }
    
  2. In controllers.js, replace the two mapsSimulator references in with maps references.

    angular.module("xPlat.controllers")
        .controller('ToDoCtrl', ['$scope', 'maps', 'storage', function ($scope, maps, storage) {
            var refresh = function () {
                $scope.todos = storage.getAll();
            }
    
  3. In services.js, replace the mapsSimulator service inwith the following code from the complete sample.

            .factory("maps", ["$rootScope", "$q", "$window", "$resource", "cordova", function ($rootScope, $q, $window, $resource, cordova) {
                var key = ''; // Add your Bing Maps API key
                var url = 'http://dev.virtualearth.net/REST/v1/Locations/:latitude,:longitude?key='+key;
    
                return {
                    getCurrentPosition: function () {
                        return cordova.ready.then(function () {
                            var deferred = $q.defer();
                            $window.navigator.geolocation.getCurrentPosition(function (successValue) {
                                $rootScope.$apply(function () {
                                    deferred.resolve(successValue);
                                });
                            }, function (errorValue) {
                                $rootScope.$apply(function () {
                                    deferred.reject(errorValue);
                                });
                            });
    
                            return deferred.promise;
                        });
                    },
    
                    getAddressFromPosition: function (position) {
                        return $resource(url, {})
                            .get({ latitude: position.coords.latitude, longitude: position.coords.longitude })
                            .$promise.then(function(response) {
                                return response.resourceSets[0].resources[0].address.formattedAddress;
                            }, function (error) {
                                return position.coords.latitude + "," + position.coords.longitude
                            });
                    }
                }
            }])
    
  4. Add the Cordova Geolocation plugin to the app by double-clicking config.xml in Solution Explorer, choosing the Plugins tab, and then choosing Geolocation.

    For more information, see Manage Plugins for Apps Built with Visual Studio Tools for Apache Cordova.

  5. Choose Add to add the plugin.

  6. Get a Bing Maps key and include it where instructed in the updated code in services.js.

Add Azure Mobile Services

The complete sample includes additional code to store and retrieve task list items using Azure Mobile Services. This code is implemented as an additional service (named azureStorage) in services.js. You can obtain this code from the complete sample app, or you can follow the instructions here to add the service.

To add Azure Mobile Services to the app

  1. If you don't already have one, create a Microsoft Azure account.

  2. Follow instructions in add a connected service to add Azure Mobile Services to your app and to create a SQL database.

    Note

    If you don't already have a services.js file in your project, it will be added when you finish adding the connected service. The resulting code will need to be replaced with code from the ToDoList sample app.

  3. In services.js, uncomment the following lines of code for the generic "storage" service.

                // var azureService = $injector.get('azureStorage');
                // return azureService.isAvailable ? azureService : $injector.get('localStorage');
    

    And remove the next line of code:

                return $injector.get('localStorage');
    

    After uncommenting the code and removing the specified code, the generic "storage" service code will look like this.

            .factory("storage", ["$injector", function ($injector) {
                var azureService = $injector.get('azureStorage');
               return azureService.isAvailable ? azureService : $injector.get('localStorage');
    
            }])
    
  4. In services.js, add the code for the Azure service where indicated by code comments.

            // To support Azure, add Azure storage service
            // code here ("azureStorage").
    
            .factory("azureStorage", ["$q", "$resource", "$rootScope", "guidGenerator", function ($q, $resource, $rootScope, guidGenerator) {
                var azureMobileServicesInstallationId = guidGenerator();
                var azureMobileServicesKey = ''; // Add your Azure Mobile Service Application Key
                var azureMobileServicesAddress = ''; // Add your Azure Mobile Service Application URL
                var azureMobileServicesTableAddress = azureMobileServicesAddress + 'tables/todoitem/:id';
                var headers = {
                    'X-ZUMO-APPLICATION': azureMobileServicesKey,
                    'X-ZUMO-INSTALLATION-ID': azureMobileServicesInstallationId,
                    'X-ZUMO-VERSION': 'ZUMO/1.0 (lang=Web; os=--; os_version=--; arch=--; version=1.0.20218.0)',
                    'Content-Type':'application/json'
                };
    
                var toDoItem = $resource(azureMobileServicesTableAddress, { id: '@id' }, {
                    'query': {
                        method: 'GET',
                        params: { $top: '1000' },
                        isArray: true,
                        headers: headers
                    },
                    'delete': {
                        method: 'DELETE',
                        headers: headers
                    },
                    'save': {
                        method: 'POST',
                        headers: headers
                    },
                    'update': {
                        method: 'PATCH',
                        headers: headers
                    }
                });
    
    
                var azureStorage = {
                    getAll: function () {
                        return toDoItem.query();
                    },
    
                    create: function (text, address) {
                        var item = new toDoItem({
                            text: text,
                            address: address,
                            done: false
                        });
    
                        return item.$save();
                    },
    
                    update: function (item) {
                        return item.$update();
                    },
    
                    del: function (item) {
                        return item.$delete();
                    },
                };
    
                Object.defineProperty(azureStorage, "isAvailable", {
                    enumerable: false,
                    get : function(){ return azureMobileServicesKey && azureMobileServicesAddress; },
                });
    
                return azureStorage;
            }])
    
  5. Get the Azure Mobile Service application key and URL that is associated with your Azure account, and include them where directed in the preceding code.

  6. Add the Cordova Azure Mobile Services plugin to the app by double-clicking config.xml in Solution Explorer, choosing the Plugins tab, and then choosing Azure Mobile Services Client.

    For more information, see Manage Plugins for Apps Built with Visual Studio Tools for Apache Cordova.

Download the toolsGet the Visual Studio Tools for Apache Cordova or learn more