Monday, January 19, 2015

Using Ionic with Windows 8, Windows Phone + Cordova


UPDATE 4/29/2015: See this updated post for Visual Studio 2015 RC! (Below is for CTP3)

Ionic has been gaining in popularity as a free and open source mobile development framework. It leverages AngularJS and SASS to provide a quick start to mobile development for iOS, Android and Windows.

But getting Ionic to work when targeting Windows 8 or Windows Phone apps with CTP3 of Visual Studio Tools for Apache Cordova isn't quite straightforward due to some security context restrictions in Windows 8 apps.

So here is a walk through for getting started with Ionic in VSCordova, along with the "gotchas" for Windows apps:
  1. First note that these steps are for CTP3 of VSCordova! Future releases will likely fix some of the issues presented here.
  2. Create a new Blank App (Apache Cordova) project:

  3. Install Ionic. Here we will use Nuget, but in the future you will likely be able to use Bower for JS packages.
    • Select Tools / NuGet Package Manager / Package Manager Console
    • type in:

      Install-Package ionic
    • be patient, this takes a bit

  4. Install JQuery 2. This is required because it fixes some security context restrictions in Win8 apps.
    • From the NuGet prompt, type in:

      Install-Package jQuery
  5. Let's replace the contents of index.html with a basic ionic template and the required includes:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
        <title>Ionic VSCordova</title>
        <link href="Content/ionic.css" rel="stylesheet" />
        <link href="css/index.css" rel="stylesheet" />
        <script src="cordova.js"></script>
        <script src="scripts/platformOverrides.js"></script>
        <script src="scripts/jquery-2.1.3.js"></script>
        <script src="scripts/ionic.bundle.js"></script> 
        <script src="scripts/index.js"></script>
    </head>
    <body ng-app="ionicApp" ng-csp>

        <ion-nav-bar class="bar-positive">
            <ion-nav-back-button class="button-icon ion-arrow-left-c">
            </ion-nav-back-button>
        </ion-nav-bar>

        <ion-nav-view></ion-nav-view>

        <script id="templates/tabs.html" type="text/ng-template">
            <ion-tabs class="tabs-icon-top tabs-positive">

                <ion-tab title="Home" icon="ion-home" href="#/tab/home">
                    <ion-nav-view name="home-tab"></ion-nav-view>
                </ion-tab>

                <ion-tab title="About" icon="ion-ios7-information" href="#/tab/about">
                    <ion-nav-view name="about-tab"></ion-nav-view>
                </ion-tab>

                <ion-tab title="Contact" icon="ion-ios7-world" ui-sref="tabs.contact">
                    <ion-nav-view name="contact-tab"></ion-nav-view>
                </ion-tab>

            </ion-tabs>
        </script>

    </body>

    </html>

  6. Now let's add in our Angular code to initialize our controller and set up our views. Open index.js and paste the following code right after the:

    "use strict";

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

        app.config(function ($stateProvider, $urlRouterProvider) {

            $stateProvider
              .state('tabs', {
                  url: "/tab",
                  abstract: true,
                  templateUrl: "templates/tabs.html"
              })
              .state('tabs.home', {
                  url: "/home",
                  views: {
                      'home-tab': {
                          templateUrl: "partials/home.html",
                          controller: 'HomeTabCtrl'
                      }
                  }
              })
              .state('tabs.personnel', {
                  url: "/personnel",
                  views: {
                      'home-tab': {
                          templateUrl: "partials/personnel.html",
                          controller: 'PersonnelTabCtrl'
                      }
                  }
              })
              .state('tabs.about', {
                  url: "/about",
                  views: {
                      'about-tab': {
                          templateUrl: "partials/about.html"
                      }
                  }
              })
              .state('tabs.contact', {
                  url: "/contact",
                  views: {
                      'contact-tab': {
                          templateUrl: "partials/contact.html"
                      }
                  }
              });

            $urlRouterProvider.otherwise("/tab/home");

        })

        app.controller('HomeTabCtrl', function ($scope) {
            console.log('HomeTabCtrl');
        });

        app.controller('PersonnelTabCtrl', function ($scope) {
            $scope.items = [
                { id: 1, name: "Kirk, James T." },
                { id: 2, name: "McCoy, Leonard" },
                { id: 3, name: "Scott, Montgomery" },
                { id: 4, name: "Uhura, Nyota" },
                { id: 5, name: "Sulu, Hikaru" },
                { id: 6, name: "Chekov, Pavel" },
                { id: 7, name: "Chapel, Christine" },
                { id: 8, name: "Rand, Janice" }
            ];
        });



  7. The code above references four partials: about, contact, home, and personnel. Let's go ahead and create those. Create a new subfolder in the project named "partials" and add the following files:

    about.html
    contact.html
    home.html
    personnel.html


    Inside each of the four partials above, create an ionic view and add some content inside (it doesn't matter what, be creative)... and set the view-title to an appropriate string to display in the header.

  8. <
    ion-view view-title="About">
        <ion-content class="padding">
            <p>ABOUT: this is just a little demo of Ionic working in VSCordova!</p>
        </ion-content>
    </ion-view>
  9. For home.html, let's add a View that links to personnel.

  10. <
    ion-view view-title="Home">
        <ion-content class="padding">
             <a class="button icon icon-right ion-chevron-right" href="#/tab/personnel">Personnel List</a>
        </ion-content>
    </ion-view>
  11. For the personnel.html, let's show an ionic list:

  12. <
    ion-view view-title="Personnel">
        <ion-content class="padding">
            <p>This ion list directive is great, but be sure to also checkout the collection repeat directive when scrolling through large lists.</p>
            <ion-list>
                <ion-item ng-repeat="item in items"
                          item="item">
                    {{ item.id }}: {{ item.name }}
                </ion-item>
            </ion-list>
            <p>
                <a class="button icon ion-home" href="#/tab/home"> Home </a>
            </p>
        </ion-content>
    </ion-view>

  13. Run the project using the Windows or Windows Phone Emulator, and you'll get an ugly blank screen! If you look at the JavaScript Console in Visual Studio, you will see:

    Error: [$compile:tplrt] Template for directive 'ionTabNav' must have exactly one root element. 

    This error in CTP3 is due to an issue in winstore-jscompat.js, which is used by the Cordova tooling to wrap security context issues in Win8 Store apps. To fix this problem, open the following file in the project:

    \merges\windows\scripts\winstore-jscompat.js

    ... and replace it with the fork provided here:

    https://github.com/ClemMakesApps/winstore-jscompat/blob/master/winstore-jscompat.js
  14. Run the project again, and you should be good to go! Here is a screenshot of Ionic running in a Windows Phone 8 Emulator...



2 comments:

  1. The sharing this way of blog post looks was really amazing. Selenium Training I agree that selenium automation IT right now and it one the best future platform to yours confidence level working style.
    Selenium Training in Chennai

    ReplyDelete
  2. The Window Phone is centered on a pair of hubs; ponsisting of pictures, people, music, games, video, office and marketplace. oukitel

    ReplyDelete