Статьи

Бэкэнд-сервисы Ionic и Telerik: здоровое партнерство

Автор Джен Лупер для блога Telerik.

Создание приложений с использованием гибридных мобильных технологий позволило разработчикам развернуть красивые продукты в рекордно короткие сроки. Недавно я заполнил целое приложение от эскиза до запуска за одну неделю, чтобы поймать праздничных покупателей. Создание отличного пользовательского интерфейса с использованием хороших инструментов разработки веб-интерфейса упрощает работу с визуальной точки зрения, но настоящая сущность приложения — его данные, поэтому нам нужен быстрый способ создания веб-интерфейса и надежный способ подключить его к надежному бэкэнду. , Для моего недавнего проекта приложения и для этого учебного руководства я использовал серверные службы Ionic и Telerik, которые являются частью платформы Telerik и предоставляют чрезвычайно удобное решение для управления данными, разработанное специально для разработчика, которому нужна скорость, точность, безопасность и простота. из-развертывания.

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

Оставайтесь с нами позже в серии для объявления об этом проекте! Оповещение о спойлере: выигрыш!

Я собираюсь назвать это приложение «Pntry» (потому что удаление гласных делает вещи крутыми). Вариант использования состоит в том, чтобы связать потребности местных продовольственных банков с донорами и клиентами, чтобы продовольственные банки могли более эффективно удовлетворять потребности своих клиентов, а доноры могли узнать, что необходимо, и настроить свои пожертвования.

Это довольно сложный проект, поэтому я собираюсь разбить эти уроки на три части:

  1. В первой части мы настроим нашу рабочую среду и завершим экраны входа и регистрации.
  2. Во второй части мы создадим формы банка продуктов питания, с помощью которых они запрашивают пожертвования определенных продуктов питания.
  3. В третьей части мы создадим приложение на основе ролей, создав области для использования банком продуктов питания и области для использования донором.

Давайте начнем!

Примечание. На данный момент я использую инструменты Ionic CLI для локального создания приложения, но в следующем уроке мы собираемся перенести нашу кодовую базу в платформу Telerik. Это еще больше ускорит разработку и предоставит доступ к превосходному набору инструментов разработчика, предлагаемых Платформой. На данный момент, однако, мы собираемся строить локально, чтобы настроить наш рабочий процесс.

Это просто, чтобы создать базовое приложение для Ionic и быстро его обработать. Следуйте этим инструкциям, чтобы установить Ionic. В командной строке убедитесь, что вы находитесь в каталоге, в котором хотите работать, и создайте приложение, введя:

$ ionic start pntry sidemenu

Эта команда запускает процесс создания леса Ionic:

леса ионные приложения

Измените каталоги на каталог pntry, который был только что создан:

$cd pntry

… И введите:

$ionic serve

Если вы правильно установили все зависимости Ionic, откроется окно браузера, в котором отображается базовое приложение с некоторыми заглушенными данными:

пустое приложение Ionic

Мы собираемся изменить приложение, чтобы создать что-то вроде этого:

каркасы для Pntry

Я разобрал этот Ionic-проект до отказа и создал базовое приложение, которое доступно вам в GitHub. Это просто скелетное приложение с несколькими цветами, и большинство страниц, которые мы хотим использовать, предварительно созданы и связаны с боковым меню, к которому я добавил иконки, потому что я немного схожу с ума по иконкам. Загрузите этот код и замените /wwwпапку в только что созданном приложении Ionic на /wwwпапку в этой кодовой базе. Перезапустите Ionic, набрав rв терминале; Вы должны увидеть новую кодовую базу.

Примечание. Если у вас уже установлен Ionic и вы знакомы с процессом установки, вы можете просто выйти из любых запущенных в данный момент процессов Ionic, извлечь этот базовый проект из github и разархивировать его, перейдите в папку, в которой находится код, и введите $ionic serve

Приложение должно выглядеть так:

закрытое приложение

… и с открытым боковым меню:

открыть приложение

Структурирование приложения

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

Ниже приведено базовое описание различных файлов JavaScript в приложении:

  1. app.js включает в себя маршруты, которые необходимо знать приложению для перехода от страницы к странице
  2. controllers.js содержит функции, которые позволяют пользователю взаимодействовать с внешним интерфейсом так, чтобы данные достигали внутреннего интерфейса
  3. service.jsобрабатывает взаимодействие между приложением и серверной частью и возвращает данные обратно во внешний интерфейс, где они отображаются, без необходимости обновления страницы из-за двусторонней привязки данных Angular. Это все довольно волшебно.

Идите вперед и добавьте services.jsфайл в /www/jsпапку. Мы уточним это, работая над этим учебником. Добавьте ссылку на этот файл index.htmlпод ссылкой controllers.js:

<script src="js/services.js"></script>

Добавьте следующую строку в services.jsфайл:

angular.module('pntry.services', [])

Добавьте ссылку на этот сервисный файл в первой строке app.js:

angular.module('pntry', ['ionic', 'pntry.controllers', 'pntry.services'])

Включение внутренних сервисов

Теперь пришло время подключить Telerik Backend Services к нашему веб- интерфейсу, чтобы мы могли заставить эти процедуры входа в систему и регистрации действительно что-то делать. Backend Services — это облачное решение для хранения данных вашего приложения. Чтобы получить к нему доступ, мы собираемся использовать JavaScript SDK (хотя это не относится к нашему приложению, существует множество других доступных интеграций — вы можете узнать больше, прочитав документацию .

Включите файл Backend Service в вашу кодовую базу. Самый простой способ сделать это — установить его через Bower (обратите внимание, что он использует прежнее имя Backend Services, Everlive):

$bower install everlive

Если у вас не установлен Bower, вы можете легко установить его через npm, используя npm install -g bower

Bower устанавливает файлы в bower_componentsпапку в корне. Переместите everlive.all.min.jsфайл, установленный Bower, в новую www/lib/everliveпапку и укажите его index.htmlпод строкой со ссылкой на ionic.bundle.js:

<script src="lib/everlive/min/everlive.all.min.js"></script>

Перейдите на платформу Telerik и войдите в систему.

Не беспокойтесь, если у вас нет учетной записи Telerik Platform; Вы можете попробовать это бесплатно в течение 30 дней .

Создайте новое рабочее пространство с именем Pntry и нажмите зеленую кнопку, чтобы создать проект Backend Services.

бэкенд

Вы собираетесь начать с нуля в этом проекте.

пользователей

Backend Services поставляется с некоторыми очень приятными функциями, в первую очередь для наших целей это объект Users , который похож на таблицу базы данных, которая будет заполняться нашими зарегистрированными пользователями.

пользователей

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

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

Получите ключ API из области API Key Платформы.

Ключ API

Теперь мы можем начать улучшать наш сервисный слой. В этом services.jsфайле добавьте наш первый объект Factory и добавьте свой собственный ключ API:


angular.module('pntry.services', [])

.factory('API', function() {

  var api_key = 'your-api-key';

    return api_key;

});


Примечание: лучшие практики требуют, чтобы вы не хранили свой ключ API в своем приложении, а скорее создавали спокойную конечную точку, из которой вы можете доставить ключ … но это тема для другого урока!

Наш сервисный слой будет содержать все обращения к бэкэнду. Другие сервисные функции смогут получить доступ к этому ключу API, вызвав фабрику.

Заполните регистрационную форму

Пока мы находимся в области Backend Services, давайте добавим еще одно поле, которое мы хотим записать при регистрации. Это будет название организации, чтобы мы могли определить название банка продуктов питания. В области «Пользователи» щелкните значок структуры данных справа:

значок данных

Добавьте элемент в таблицу Users с именем OrganizationName и нажмите «добавить» и «сохранить».

Добавьте предмет

Добавьте поле /www/templates/register.htmlпод открывающим элементом списка карт, чтобы новое поле ввода появилось вверху регистрационной формы:


<label class="item item-input">
<span class="input-label">Organization Name</span>
<input type="text" name="displayname" ng-model="registerData.organizationname"></label>


Завершите функции регистрации

Теперь нам нужно обработать регистрационную форму. Мы начнем с создания фабрики пользователей в services.jsрамках фабрики API:


.factory('User', function (API) {

var el = new Everlive({
        apiKey: API,
        url: '//api.everlive.com/v1/',
        scheme: 'https'
     });
  return {
    register: function(registerData){          
        return el.Users.register(
            registerData.username, 
            registerData.password, 
              { 
                Email: registerData.email, 
                DispayName: registerData.displayname,
                OrganizationName: registerData.organizationname
               })
            .then(function (data) {
                return data;
            },
            function(error) {
                return error;
            });               
    }
  }
});

Затем включите controller.jsиспользование этой новой фабрики, добавив ее ссылку в начало этого файла. Мы также используем некоторые дополнительные возможности, предоставляемые Ionic для пользовательского интерфейса, поэтому убедитесь, что вершина controller.jsнапоминает эту строку:

.controller('AppCtrl', function($state, $scope, $ionicModal, $ionicPopup, User) {...

В том числе $stateпозволяет нам перейти на новую страницу после регистрации и авторизации. $ionicPopupэто чистое маленькое всплывающее окно, которое полезно для отображения ошибок регистрации, сгенерированных из серверной части. И пользователь — это имя фабрики, которую вы создали на уровне сервисов. В вашем контроллере ссылайтесь на заводскую настройку User.register, чтобы передавать данные обратно и обратно в сервис.

Наконец, уточните doRegister()функцию в контроллере:

// Perform the register action when the user submits the registration form
$scope.doRegister = function() {

    User.register($scope.registerData).then(function(data){
      if(data.result){
        //log me in
        $scope.loginData.username = $scope.registerData.username;
        $scope.loginData.password = $scope.registerData.password;
        $scope.doLogin();
        $scope.closeRegister();
        $state.go("app.inventory");
    }
    else{
      $ionicPopup.alert({
        title: status.data.message,
        template: 'Please try again!'
        });
      }
    });
}

Теперь вы сможете открыть регистрационную форму в своем приложении, заполнить ее, нажать «Зарегистрироваться» и просмотреть свои данные в Backend Services в таблице «Пользователь».

Создание логина и аутентификации

По умолчанию сгенерированный нами проект Ionic поставляется со встроенным экраном входа. Мы собираемся добавить к нему экран регистрации, чтобы продовольственная кладовая могла создавать профиль и иметь собственные данные. Большая часть приложения должна быть защищена паролем, поэтому мы собираемся сохранить токен, сгенерированный Backend Services, чтобы помочь с нашей аутентификацией.

Добавьте loginфункцию в services.jsфабрику пользователей под функцией регистрации:

login: function(loginData) {                
    return el.Users.login(
        loginData.username,
        loginData.password)
        .then(function (data) {
            return data;
        },
        function(error) {
            return error;
        });
},

Теперь в контроллере все становится интересным. Мы собираемся использовать localStorage для сохранения токена, который Backend Service отправляет обратно, чтобы мы могли использовать его в будущих взаимодействиях.

Перезаписать текущую doLoginфункцию следующим кодом:

// Perform the login action when the user submits the login form
$scope.doLogin = function() {
    User.login($scope.loginData).then(function(data){
      if(data.result){
        localStorage.setItem("token",data.result.access_token);
        $state.go("app.inventory");
        $scope.loginmodal.hide();
      }
      else{
        $ionicPopup.alert({
            title: data.message,
            template: 'Please try again!'
          });
      }
    });
};

Наконец, мы можем добавить тест, чтобы убедиться, что у нас есть токен и что он действителен; если это не так, мы вернем пользователя обратно на домашнюю страницу; если это так, мы разрешаем доступ к данной области. Добавьте этот фрагмент кода выше предыдущего кода:

$scope.testLoginStatus = function() {

    var token = localStorage.getItem("token");        
     User.me(token).then(function(data){
      console.log(data)
      if(!data.result){
        $ionicPopup.alert({
            title: 'Your session has expired',
            template: 'Please login!'
          });
        //go home
        $state.go("app.home");          
        }
    });    
};

Теперь мы можем создать сервис для проверки статуса пользователя и убедиться, что токен аутентификации был установлен при входе в систему:

//am I logged in with a valid token?
me: function(token) {
    return el.Users.currentUser(
        {headers: {'Authorization':'Bearer '+token}})
    .then(function (data) {
        return data;
    },
    function(error) {
        return error;
    });
}

Добавьте тест токена click ( ng-click="testLoginStatus()") для каждого элемента меню в /www/templates/menu.html:

<ion-list>
    <ion-item nav-clear menu-close ng-click="testLoginStatus()" href="#/app/donationrequests">
      <i class="icon ion-help-buoy"></i> Donation Requests
    </ion-item>
    <ion-item nav-clear menu-close ng-click="testLoginStatus()" href="#/app/requestdonation">
      <i class="icon ion-speakerphone"></i> Request A Donation
    </ion-item>
    <ion-item nav-clear menu-close ng-click="testLoginStatus()" href="#/app/inventory">
     <i class="icon ion-clipboard"></i> Inventory
   </ion-item>
    <ion-item nav-clear menu-close ng-click="testLoginStatus()" href="#/app/needs">
      <i class="icon ion-compose"></i> Current Needs
   </ion-item>
</ion-list>

Проверка в реальных условиях

Теперь весь controllers.jsфайл должен выглядеть так:

angular.module('pntry.controllers',[])

.controller('AppCtrl', function($state, $scope, $ionicModal, $ionicPopup, User) {
  // Form data for the login modal
  $scope.loginData = {
    username: null,
    password: null
  };

  $scope.registerData = {
    username: null,
    password: null,
    email: null,
    displayname: null,
    organizationname: null
  };


  // Create the login modal that we will use later
  $ionicModal.fromTemplateUrl('templates/login.html', {
    scope: $scope
  }).then(function(loginmodal) {
    $scope.loginmodal = loginmodal;
  });

  // Create the login modal that we will use later
  $ionicModal.fromTemplateUrl('templates/register.html', {
    scope: $scope
  }).then(function(registermodal) {
    $scope.registermodal = registermodal;
  });

  $scope.testLoginStatus = function() {

    var token = localStorage.getItem("token");        
     User.me(token).then(function(data){
      console.log(data)
      if(!data.result){
        $ionicPopup.alert({
            title: 'Your session has expired',
            template: 'Please login!'
          });
        //go home
        $state.go("app.home");          
        }
    });    
  };

  //open/close routines
  $scope.openLogin = function() {
    $scope.loginmodal.show();
  };
  $scope.closeLogin = function(){
    $scope.loginmodal.hide();
  };
  $scope.openRegister = function() {
    $scope.registermodal.show();
  };
  $scope.closeRegister = function(){
    $scope.registermodal.hide();
  };

  // Perform the login action when the user submits the login form
  $scope.doLogin = function() {
    User.login($scope.loginData).then(function(data){
      if(data.result){
        localStorage.setItem("token",data.result.access_token);
        $state.go("app.inventory");
        $scope.loginmodal.hide();
      }
      else{
        $ionicPopup.alert({
            title: data.message,
            template: 'Please try again!'
          });
        }
    });
  };

  // Perform the register action when the user submits the registration form
  $scope.doRegister = function() {

    User.register($scope.registerData).then(function(data){
      if(data.result){
        //log me in
        $scope.loginData.username = $scope.registerData.username;
        $scope.loginData.password = $scope.registerData.password;
        $scope.doLogin();
        $scope.closeRegister();
        $state.go("app.inventory");
    }
    else{
      $ionicPopup.alert({
        title: status.data.message,
        template: 'Please try again!'
        });
      }
    });
  }
});
```
and the entire services.js file looks like this:
```
angular.module('pntry.services', [])

.factory('API', function() {

  var api_key = 'your-api-key';

    return api_key;


})

.factory('User', function (API) {

var el = new Everlive({
        apiKey: API,
            url: '//api.everlive.com/v1/',
            scheme: 'https'
        });
  return {
    register: function(registerData){          
        return el.Users.register(
            registerData.username, 
            registerData.password, 
              { 
                Email: registerData.email, 
                DispayName: registerData.displayname,
                OrganizationName: registerData.organizationname
               })
            .then(function (data) {
                return data;
            },
            function(error) {
                return error;
            });               
    },
    login: function(loginData) {                
        return el.Users.login(
            loginData.username,
            loginData.password)
            .then(function (data) {
                return data;
            },
            function(error) {
                return error;
            });
    },
    me: function(token) {
        return el.Users.currentUser(
            {headers: {'Authorization':'Bearer '+token}})
            .then(function (data) {
                return data;
            },
            function(error) {
                return error;
            });
    }
  }
});

Ура!

Мы успешно создали интерфейс для нашего приложения с базовой безопасностью, включая процедуры регистрации и входа в систему, соединяя интерфейс Ionic с Telerik Backend Services. В процессе мы создали прочную структуру для нашего приложения со слоем сервисов, отделенным от контроллера и представления, как нас научила мама. В следующем уроке мы создадим четыре экрана, которые банк продуктов сможет использовать для запроса пожертвований и управления запасами.

Изображение заголовка любезно предоставлено WEBN-TV