company_banner

Используем AngularJS в Windows Phone 8.1 приложениях



    В этом посте я расскажу вам как подключить и начать использовать популярный JavaScript фреймворк AngularJS для разработки приложений для Windows Phone 8.1. Вы сможете подключить AngularJS к своему проекту и начать использовать его возможности.

    Создаем проект и подключаем AngularJs


    Создаем новый проект для Windows Phone 8.1 на JavaScript по шаблону Blank App.



    Подключаем AngularJS. Он доступен в виде установочного пакета в NuGet.
    Открываем NuGet Package Manager Console и выполняем команды:

    install-package AngularJS.Core
    install-package AngularJS.Animate
    install-package Angular.UI.UI-Router
    

    AngularJS.Core – библиотека с базовыми возможностями AngularJS.

    AngularJS.Animate – анимационные возможности.

    Angular.UI.UI-Router – навигация, работа с представлениями.

    Angular-WinJS — чтобы получить возможность использовать AngularJS вместе с WinJS, вам нужно установить этот модуль. К сожалению, в настоящее время он не опубликован в виде пакета NuGet и нам придется скачать его с GitHub вручную.

    Добавьте скачанный скрипт в папку scripts в проекте:



    Вносим изменения в библиотеки


    Как только вы попробуете подключить библиотеки Angular на вашу страницу и запустить приложение, произойдет страшное, то есть ошибка.



    В соответствии с моделью безопасности Windows Phone приложений, вы не можете динамически менять содержимое элементов страницы. Но можете это делать внутри конструкции

    MSApp.execUnsafeLocalFunction(function () {
    
    });
    


    То есть, в файле scripts/angular.js необходимо обернуть все изменения innerHTML или вызовы метода prepend или insert.. в эту конструкцию.

    Исправленный файл доступен по ссылке на Github

    Используем AngularJS на странице приложения


    1. Откроем файл default.html, добавим ссылки на библиотеки AngularJS.



    В теле страницы разместим специальный контейнер, в который средствами AngularJS мы будем загружать представление:

    <div ui-view></div>
    

    Полный код файла default.html
    <!DOCTYPE html >
    <html>
    <head>
        <meta charset="utf-8" />
        <title>demo</title>
    
        <link href="//Microsoft.Phone.WinJS.2.1/css/ui-light.css" rel="stylesheet" />
        <script src="//Microsoft.Phone.WinJS.2.1/js/base.js"></script>
        <script src="//Microsoft.Phone.WinJS.2.1/js/ui.js"></script>
        <!-- Angular references -->
        <script src="/scripts/angular.js"></script>
        <script src="/scripts/angular-animate.js"></script>
        <script src="/scripts/angular-ui-router.js"></script>
        <script src="/scripts/angular-winjs.js"></script>
        <!-- demo references -->
        <link href="/css/default.css" rel="stylesheet" />
        <script src="/js/default.js"></script>
    
    </head>
    <body class="phone" >   
        <div ui-view></div>
    </body>
    </html>
    


    2. Создадим новую папку views в который мы будем хранить представления для страниц.
    3. В папке views создадим файл mainView.html для представления главной страницы.
    Наша основная страница будет содержать только поздравление с прошедшим праздником и кнопку на панели действий.



    Полный код файла mainView.html

    <div class="demoView fragment">
        <h1 style="font-size:2em">
            {{greeting}}
        </h1>   
        <win-app-bar>
            <win-app-bar-command icon="'accept'" label="'ok'" ng-click="ok()"></win-app-bar-command>
        </win-app-bar>
    </div>
    


    Конструкция {{greeting}} поможет нам вывести значение переменной, которую мы определим в контроллере, а кнопка подтверждения будет представлять собой кнопку на панели действий, созданную средствами WinJS.

    4. Откроем js/default.js – основной файл приложения, в котором будет находиться весь код и заменим его содержимое.



    Полный код файла default.js
     (function () {
        "use strict";
    
        var app = WinJS.Application;
        var activation = Windows.ApplicationModel.Activation;
    
        var angular_app = angular.module('demo', ['ui.router', 'ngAnimate', 'winjs']);
    
        app.onactivated = function (args) {
            if (args.detail.kind === activation.ActivationKind.launch) {
                if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                    
                } else {
                    
                }
    
                var angularLoadedSignal = new WinJS._Signal();
                angular.element(document).ready(function () {
                    try {
                        angular.bootstrap(document, ['demo']);
                        angularLoadedSignal.complete();
                    } catch (e) {
                        
                        if (!(typeof e.message == 'string' || e.message instanceof String)) {
                            throw e;
                        }
    
                        if (e.message.indexOf('[ng:btstrpd]') !== 0) {
                            throw e;
                        }
                    }
                });
    
                args.setPromise(angularLoadedSignal.promise);
    
            }
        };
    
        app.oncheckpoint = function (args) {
          
        };
    
        //наполняем представление данными и обрабатываем события
        angular_app.controller('mainViewCtrl', ['$scope', function ($scope) {
    
            $scope.greeting = 'С Днем народного единства!';
    
            $scope.ok = function () {
                var msgpopup = new Windows.UI.Popups.MessageDialog("Если вы хотите закрыть окно, нажмите на кнопку","Отправить поздравление"); 
     
                msgpopup.commands.append(new Windows.UI.Popups.UICommand("ok", function () {
                   
                }));
     
                msgpopup.showAsync();
            };
    
        }]);
    
        //настраиваем, указываем шаблон и контроллер
        angular_app.config(function ($stateProvider) {
            $stateProvider
             .state('mainView', {
                 url: '/mainView',
                 templateUrl: '/views/mainView.html',
                 controller: 'mainViewCtrl',
             });
        });
    
        //переходим на view при открытии приложения
        angular_app.constant('homeStateName', 'mainView');
        angular_app.run(function (navigationSvc) {
            navigationSvc.goHome();
        });
            
        (function () {
            var NavigationSvc = function ($q, $state, adapterSvc, homeStateName) {
                WinJS.Navigation.addEventListener('navigating', function (args) {
                    var targetState = args.detail.location;
                    var angularPromise = $state.go(targetState, args.detail.state);
                    args.detail.setPromise(adapterSvc.toWinJSPromise(angularPromise));
                });
    
                this.goHome = function () {
                    return adapterSvc.toAngularPromise(WinJS.Navigation.navigate(homeStateName));
                };
    
                this.navigateTo = function (view, initialState) {
                    return adapterSvc.toAngularPromise(WinJS.Navigation.navigate(view, initialState));
                };
    
                this.goBack = function () {
                    return adapterSvc.toAngularPromise(WinJS.Navigation.back());
                };
    
                this.goForward = function () {
                    return adapterSvc.toAngularPromise(WinJS.Navigation.forward());
                }
            };
    
            angular_app.service('navigationSvc', NavigationSvc);
        }());
    
        angular_app.service('adapterSvc', ['$q', function ($q) {
            return {
                toAngularPromise: function (winjsPromise) {
                    var deferred = $q.defer();
    
                    winjsPromise.then(function (value) {
                        deferred.resolve(value);
                    }, function (err) {
                        deferred.reject(err);
                    }, function (value) {
                        deferred.notify(value);
                    });
    
                    return deferred.promise;
                },
    
                toWinJSPromise: function (angularPromise) {
                    var signal = new WinJS._Signal();
    
                    angularPromise.then(function (value) {
                        signal.complete(value);
                    }, function (err) {
                        signal.error(err);
                    }, function (value) {
                        signal.progress(value);
                    });
    
                    return signal.promise;
                }
            }
        }]);
    
        app.start();
    })();
    


    В этом коде мы:
    • Инициализируем библиотеки AngularJS и заставляем выполниться механизм bootstrap при загрузке страницы приложения. Подробнее как работает bootstrap в AngularJS описано в руководстве.
    • Создаем контроллер demoViewCtrl, в котором создаем переменную и обрабатываем событие нажатия на кнопку на панели действий
    • Реализуем навигацию и загрузку представления в контейнер.
      Некоторые детали про навигацию
      Как вы знаете, в WinJS есть своя библиотека для навигации WinJS.Navigation и вы можете создавать одностраничные приложения (single page apps), где все остальные страницы подгружаются в DOM одной основной страницы, или использовать привычную модель навигации и осуществлять переходы между страницами.

      AngularJS имеет возможности навигации между представлениями в рамках одностраничного приложения, которые очень похожи на концепцию навигации в WinJS. Функции работы с навигацией доступны в виде отдельного модуля на сайте AngularJS. Популярной альтернативой модуль UI Router (мы уже установили из NuGet).

      Начав использовать AngularJS вы можете выбирать какими механизмами (WinJS или AngularJS) вы будете пользоваться в своем проекте. Единственное что надо помнить – это то, что у тебе телефона есть аппаратная кнопка Back, про которую AngularJS ничего не знает, и чтобы она работала, мы используем гибридный вариант навигации AngularJS+WinJS.

    5. Запускаем приложение. Приложение должно запуститься и загрузить представление.



    Заключение


    Все больше технологий, которые мы привыкли видеть и использовать в веб, становятся доступны для мобильных платформ. И это просто замечательно.

    Библиотеки Angular для Windows Phone


    Библиотека Angular-WinJS
    Исправленный файл angular.js
    Пример кода: ToDoList для Windows Phone 8.1 на AngularJS

    Полезные ссылки


    Документация по AngularJS
    Изучить курсы виртуальной академии Microsoft
    Попробовать Azure бесплатно на 30 дней!
    Загрузить бесплатную или пробную Visual Studio
    Стать разработчиком приложений Windows Phone
    Стать разработчиком приложений Windows Store
    • +11
    • 9,3k
    • 7
    Microsoft
    429,47
    Microsoft — мировой лидер в области ПО и ИТ-услуг
    Поделиться публикацией

    Комментарии 7

      +1
      не думаю что нужно модифицировать angularjs, можно же сделать
      angular.config(function($sceProvider) {
        $sceProvider.enabled(false);
      })
      

      это на всех нормальных браузерах замедляет работу где-то на 30%, но зато всё работает на ie
        –1
        Если мне память не изменяет, ангуляр и так не самый быстрый из фреймворков, а еще его замедлять и использовать на мобильной платформе.
        Приложения на бюджетных мобилах не будут тормозить?
          +1
          Ангуляр вполне производителен чтобы выводить тысячи сложных элементов с кучей привязанных действий на экран. Проблема скорости обычно в непродуманном дизайне и неэффективной работе с данными, потому если программист не новичок и дизайнер понимает что делает, тормозить ни на каком фреймворке не будет.
            +1
            Но менять исходники AngularJS — точно не вариант.
              +3
              Опять же, microsoft phone, можно определять или используя всякие
                <!--[if IEMobile]>
              

              замедлять только в мобильных IE

              на самом деле пользователи IE в веб разработке всегда страдают больше всех, их поддержку многие делают по остаточному принципу и это вина microsoft, по моему скромному мнению.
                +1
                Увы Conditional Comments не помогут…

                Important As of Internet Explorer 10, conditional comments are no longer supported by standards mode. Use feature detection to provide effective fallback strategies for website features that aren't supported by the browser.


                msdn.microsoft.com/en-us/library/ms537512.aspx

                PS: напомню что на WP8.x стоит IE10+
            +2
            Что бы не модифицировать код фреймворка можно также использовать специальную библиотеку от MS Open Tech, про которую недавно писали на хабре — habrahabr.ru/post/233189/ Это будет работать и с jQuery. А вообще в модели безопасности много запретов, которые приходится как-то обходить — например, нельзя подключить внешний скрипт (но можно его скачать eval'ить) :(

            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

            Самое читаемое