Статьи

Создайте приложение для обновления статуса в реальном времени с AngularJS & Firebase

Если вы потратили какое-то время на AngularJS, вы, вероятно, знакомы с Firebase — хранилищем данных в реальном времени, благодаря которому очень легко сохранять и синхронизировать данные на любой платформе. Firebase предоставляет привязку AngularJS для своей платформы AngularFire, что делает использование Firebase API еще проще.

В этом руководстве мы создадим простое приложение для обновления статуса, которое позволит нам увидеть взаимодействие AngularJS и Firebase. Для пользовательского интерфейса мы будем использовать Angular Material, который является AngularJS-реализацией Google Material Design и поставляется с большим набором отличных компонентов пользовательского интерфейса. Angular Material основан на flexbox, к которому может потребоваться некоторое привыкание, если вы еще не знакомы с ним. Мы также собираемся сосредоточиться на части аутентификации приложения, которая, как мы увидим, упрощена встроенной системой аутентификации Firebase.

Снимок экрана 1 приложения состояния в реальном времени

В этом руководстве предполагается, что вы знакомы с AngularJS и что у вас есть общее представление о том, что такое Firebase и как он работает.

Как всегда, код для этого урока можно найти на GitHub .

Установка зависимостей

Давайте начнем с установки того, что нам нужно для приложения, используя npm .

Из командной строки:

 mkdir status-app && cd status-app npm install angular-material angular-ui-router angularfire angular-md5 

Установка Angular Material предоставит нам и другие пакеты, включая самую последнюю версию AngularJS. Мы включили UI Router, так как нам нужно обрабатывать два разных состояния — одно для входа / регистрации и другое для просмотра состояний. Angular MD5 предоставит нам быстрый способ хэширования адресов электронной почты, которые будут необходимы для получения изображений Gravatar для наших пользователей.

Вам также понадобится какой-нибудь сервер для просмотра и взаимодействия с приложением. Для этого идеален http-сервер .

Настройка приложения

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

 status-app |-- components |-- auth |-- status |-- user |-- node_modules * dependencies -- app.js -- index.html -- style.css 

Давайте настроим наш файл index.html со ссылками на уже установленные нами зависимости, а также на сценарии приложения, которые мы еще не создали.

 <!-- index.html --> <!DOCTYPE html> <html> <head> <title>Status App</title> <link rel="stylesheet" href="node_modules/angular-material/angular-material.css"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=RobotoDraft:300,400,500,700,400italic"> <link rel="stylesheet" type="text/css" href="style.css"> </head> <body ng-app="statusApp"> <div layout="row"> <div flex="33" offset="33"> <div ui-view></div> </div> </div> </body> <!-- Application Dependencies --> <script src="node_modules/angular/angular.js"></script> <script src="node_modules/angular-ui-router/build/angular-ui-router.js"></script> <script src="node_modules/angular-material/angular-material.js"></script> <script src="node_modules/angular-animate/angular-animate.js"></script> <script src="node_modules/angular-aria/angular-aria.js"></script> <script src="https://cdn.firebase.com/js/client/2.2.6/firebase.js"></script> <script src="node_modules/angularfire/dist/angularfire.js"></script> <script src="node_modules/angular-md5/angular-md5.js"></script> <!-- Application Scripts --> <script src="app.js"></script> <script src="components/auth/authController.js"></script> <script src="components/auth/authService.js"></script> <script src="components/status/statusController.js"></script> <script src="components/status/statusService.js"></script> <script src="components/user/userService.js"></script> </html> 

Мы загрузили приложение в тег body и назвали его statusApp . Мы также немедленно используем Angular Material в теле, указав, что открывающий тег div должен иметь макет row . При установке макета в row все внутри контейнера будет располагаться горизонтально. Если бы мы установили макет в column , все было бы сложено вертикально.

В следующем div мы устанавливаем ширину равной 33%, добавляя значение 33 в атрибут flex . Атрибут offset позволяет нам центрировать элемент, говоря, что он должен быть перемещен вправо на треть.

Последний элемент — это наш тег пользовательского интерфейса, который является точкой, в которой будут загружены наши (еще не созданные) состояния маршрутизатора пользовательского интерфейса.

Нам также понадобится файл app.js чтобы запустить приложение.

 // app.js (function() { 'use strict'; angular .module('statusApp', ['firebase', 'ngMaterial', 'angular-md5', 'ui.router']) .config(function($stateProvider, $urlRouterProvider) { // If a route other than status is requested, // go to the auth route $urlRouterProvider.otherwise('/auth'); $stateProvider .state('auth', { url: '/auth', templateUrl: 'components/auth/authView.html', controller: 'AuthController as auth' }) .state('status', { url: '/status', templateUrl: 'components/status/statusView.html', controller: 'StatusController as status' }); }); })(); 

Как вы увидите, мы вызываем AngularJS-модуль statusApp который соответствует нашему объявлению ng-app в теге body . Мы внедрили нужные нам модули, указав их в массиве рядом с именем модуля, а затем настроили некоторую конфигурацию для приложения. В блоке конфигурации мы настроим правила для маршрутизатора пользовательского интерфейса для обработки различных состояний. Чтобы это произошло, нам нужно передать функции конфигурации $stateProvider и $urlRouterProvider .

Нам еще предстоит настроить фактические контроллеры и шаблоны для этих состояний, но здесь мы говорим о том, что когда мы находимся в URI /auth , мы хотим загрузить представление auth и контроллер auth. Это государство отвечает за предоставление пользователям логина и регистрационного окна.

После входа в систему мы хотим перейти в состояние /status которое загружает контроллер состояния и просматривать. Наконец, мы хотим отменить любые другие маршруты, поэтому сообщаем $urlRouterProvider если сомневаемся, отправляем пользователя в состояние /auth .

Немного CSS

Нам понадобится немного CSS для стилизации списков статуса в нашем приложении.

 /* style.css */ .face { border-radius: 30px; border: 1px solid #ddd; width: 48px; margin: 16px; } .remove-status { cursor: pointer; color: red; font-weight: bold; } 

Обработка аутентификации

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

ПРИМЕЧАНИЕ. Примеры кода ссылаются на мое собственное приложение Firebase, которое я создал, которым вы можете пользоваться бесплатно. Кроме того, вы можете создать свою собственную учетную запись Firebase и изменить ссылки в коде, чтобы указать на нее. Для этого см. Раздел « Добавление собственной учетной записи Firebase» в конце статьи.

Сначала давайте создадим сервис аутентификации.

 // components/auth/authService.js (function() { 'use strict'; angular .module('statusApp') .factory('Auth', AuthService); function AuthService($firebaseAuth) { var ref = new Firebase("https://statusapp.firebaseio.com"); return $firebaseAuth(ref); } })(); 

Мы даем этой factory имя Auth и устанавливаем соединение с уже созданным приложением Firebase, которое называется statusapp . Мы передаем ссылку на наше приложение на $firebaseAuth который является службой, ответственной за обработку методов аутентификации Firebase. Возвращение этого из нашего сервиса Auth позволит нам подключиться к нему с нашего контроллера.

Далее, давайте настроим контроллер аутентификации с некоторыми методами, которые будут входить и регистрировать пользователей.

 // components/auth/authController.js (function() { 'use strict'; angular .module('statusApp') .controller('AuthController', AuthController); function AuthController(Auth, $state) { var vm = this; vm.createUser = createUser; vm.login = login; function createUser() { // If there is already a user logged in, // log them out before proceeding Auth.$unauth(); Auth.$createUser({ email: vm.email, password: vm.password }).then(function(userData) { login(); }).catch(function(error) { vm.error = error; }); } function saveUser() { // TODO: save the user data at the /users endpoint } function login() { Auth.$authWithPassword({ email: vm.email, password: vm.password }).then(function(data) { vm.email = null; vm.password = null; $state.go('status'); }).catch(function(error) { console.log(error); }); } } })(); . // components/auth/authController.js (function() { 'use strict'; angular .module('statusApp') .controller('AuthController', AuthController); function AuthController(Auth, $state) { var vm = this; vm.createUser = createUser; vm.login = login; function createUser() { // If there is already a user logged in, // log them out before proceeding Auth.$unauth(); Auth.$createUser({ email: vm.email, password: vm.password }).then(function(userData) { login(); }).catch(function(error) { vm.error = error; }); } function saveUser() { // TODO: save the user data at the /users endpoint } function login() { Auth.$authWithPassword({ email: vm.email, password: vm.password }).then(function(data) { vm.email = null; vm.password = null; $state.go('status'); }).catch(function(error) { console.log(error); }); } } })(); 

Первый метод, который у нас есть на этом контроллере, — это createUser который отвечает за принятие пользовательских данных и использование сервиса Auth мы создали ранее, для создания нового пользователя в Firebase. Вы заметите, что методы Auth которые мы вызываем, нигде не были созданы нами. Скорее, эти методы на самом деле доступны из сервиса $fireabaseAuth который мы возвращаем из нашего сервиса Auth .

Когда новый пользователь успешно создан, мы вызываем метод login в login в котором мы снова используем один из встроенных методов проверки подлинности Firebase, $authWithPassword . Этот метод принимает объект с ключом электронной почты и паролем, который мы устанавливаем равным тому, что пользователь вводит в эти поля. Затем обработчик успеха позволяет нам очистить пользовательский ввод и перенаправить его на главную страницу статуса, если их вход был успешным. Если вход был неудачным, мы ловим его, а пока просто регистрируем ошибку на консоли.

Вы увидите, что в методе saveUser настоящее время у нас есть только кодовый комментарий, к которому нам нужно добавить поддержку для сохранения пользовательских данных в конечной точке /users в Firebase. Нам нужно будет создать еще один сервис для этого, что мы и сделаем в следующем разделе.

Прежде чем двигаться дальше, давайте разместим HTML-код нашей страницы аутентификации, чтобы мы могли увидеть, что у нас есть.

 <!-- components/auth/authView.html --> <md-content class="md-padding"> <md-tabs md-dynamic-height md-border-bottom> <md-tab label="login"> <md-content class="md-padding"> <h1 class="md-display-2">Login</h1> <md-input-container> <label>Email</label> <input ng-model="auth.email" type="text"> </md-input-container> <md-input-container> <label>Password</label> <input type="password" ng-model="auth.password" type="text"> </md-input-container> <md-button class="md-raised md-warn" ng-click="auth.login()">Login</md-button> </md-content> </md-tab> <md-tab label="register"> <md-content class="md-padding"> <h1 class="md-display-2">Register</h1> <md-input-container> <label>User Name</label> <input ng-model="auth.username" type="text"> </md-input-container> <md-input-container> <label>Email</label> <input ng-model="auth.email" type="text"> </md-input-container> <md-input-container> <label>Password</label> <input type="password" ng-model="auth.password" type="text"> </md-input-container> <md-button class="md-raised md-primary" ng-click="auth.createUser()"> Register </md-button> </md-content> </md-tab> </md-tabs> </md-content> 

Это довольно плотный HTML! Angular Material великолепен и обеспечивает очень приятный дизайн пользовательского интерфейса, но HTML может иметь тенденцию складываться. Однако приятно то, что у нас есть очень описательные пользовательские теги HTML, которые помогают нам понять, для чего предназначен каждый элемент.

Мы используем вкладки Angular Material для страницы входа / регистрации. Здесь работают две кнопки — одна для входа, а другая для регистрации. Вы увидите, что у нас есть объявление ng-click для каждого из них и что они вызывают соответствующие методы из authController .

Если все работает правильно, вы должны увидеть это:

Снимок экрана 2 приложения состояния в реальном времени

Снимок экрана 3 приложения состояния в реальном времени

Сохранение новых пользовательских данных

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

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

Для начала давайте создадим новый сервис, который будет отвечать за хранение данных, связанных с пользователями.

 // components/user/userService.js (function() { 'use strict'; angular .module('statusApp') .factory('User', UserService); function UserService($firebaseObject) { function newUserRef(user) { var ref = new Firebase("https://statusapp.firebaseio.com/users/" + user.uid); return $firebaseObject(ref); } function getUserData(user) { var ref = new Firebase("https://statusapp.firebaseio.com/users/" + user); return $firebaseObject(ref); } function getLoggedInUser() { var user = localStorage.getItem('firebase:session::statusapp'); if(user) { return JSON.parse(user); } } return { newUserRef: newUserRef, getUserData: getUserData, getLoggedInUser: getLoggedInUser } } })(); 

Здесь у нас есть новый заводской сервис под названием User который возвращает три метода. Вы заметите, что мы используем сервис Firebase $firebaseObject для настройки синхронизированного объекта .

Метод newUserRef отвечает за создание ключа в конечной точке /users для вновь зарегистрированного пользователя. Мы полагаемся на uid для нового пользователя, который является уникальным идентификатором, который Firebase создает для нас, который гарантированно будет отличаться для всех поставщиков аутентификации, поддерживаемых Firebase. uid форматируется с использованием метода провайдера, а затем числа, представляющего пользователя. В случае нашего простого метода входа в систему 30-й пользователь получит simplelogin:30 . Когда новый пользователь регистрируется, объект, который возвращается в случае успеха, содержит uid пользователя для этого пользователя, и это то, что позволяет нам подключиться к нему в службе User .

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

Наконец, метод getLoggedInUser позволяет нам получить доступ к данным, которые Firebase хранит в локальном хранилище для текущего пользователя, вошедшего в систему. Для нашего приложения Firebase хранит эти данные в ключе с именем firebase:session::statusapp . Поскольку данные хранятся в виде строки, мы должны применить JSON.parse чтобы превратить их в полезный объект.

Теперь, когда наш сервис User работает, давайте добавим немного логики в наш authController чтобы использовать его.

 // components/auth/authController.js (function() { 'use strict'; angular .module('statusApp') .controller('AuthController', AuthController); function AuthController(Auth, User, $state) { var vm = this; vm.createUser = createUser; vm.login = login; vm.loggedInUser; function createUser() { // If there is already a user logged in, // log them out before proceeding Auth.$unauth(); Auth.$createUser({ email: vm.email, password: vm.password }).then(function(userData) { saveUser(userData); login(); }).catch(function(error) { vm.error = error; }); } function saveUser(userData) { var user = User.newUserRef(userData); user.username = vm.username; user.email = vm.email; user.$save().then(function(success) { vm.username = null; vm.email = null; vm.password = null; $state.go('status'); }, function(error) { console.log("there was an error! " + error); }); } ... . // components/auth/authController.js (function() { 'use strict'; angular .module('statusApp') .controller('AuthController', AuthController); function AuthController(Auth, User, $state) { var vm = this; vm.createUser = createUser; vm.login = login; vm.loggedInUser; function createUser() { // If there is already a user logged in, // log them out before proceeding Auth.$unauth(); Auth.$createUser({ email: vm.email, password: vm.password }).then(function(userData) { saveUser(userData); login(); }).catch(function(error) { vm.error = error; }); } function saveUser(userData) { var user = User.newUserRef(userData); user.username = vm.username; user.email = vm.email; user.$save().then(function(success) { vm.username = null; vm.email = null; vm.password = null; $state.go('status'); }, function(error) { console.log("there was an error! " + error); }); } ... 

Мы начнем с внедрения службы User в функцию AuthController чтобы мы могли использовать ее методы в saveUser . Метод saveUser принимает в качестве аргумента некоторые пользовательские данные, которые в нашем случае будут объектом, возвращаемым Firebase при создании нового пользователя. Эти пользовательские данные передаются методу newUserRef в сервисе User который, как мы видели ранее, устанавливает новый пользовательский ключ в конечной точке /users .

Вы увидите, что мы устанавливаем некоторые свойства — username и email — для вновь созданного user . Если затем мы просто вызовем метод Ang $save AngularFire, данные будут переданы в Firebase.

Если сохранение прошло успешно, мы очищаем ввод пользователя и перенаправляем пользователя в status .

Это было много настроек! Давайте теперь перейдем к забавной части и на самом деле сохраняем и получаем статусы пользователя.

Сохранение статусов

Мы собираемся сохранить все пользовательские статусы в конечной точке /status в нашем хранилище данных Firebase. Чтобы настроить это соединение, давайте создадим новый сервис под названием Status .

 // components/status/statusService.js (function() { 'use strict'; angular .module('statusApp') .factory('Status', StatusService); function StatusService($firebaseArray) { var ref = new Firebase("https://statusapp.firebaseio.com/status"); return $firebaseArray(ref); } })(); 

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

Имея службу Status , мы можем теперь использовать ее в контроллере, который будет отвечать за подачу данных о состоянии в представление и добавление новых статусов.

  // components/status/statusController.js (function() { 'use strict'; angular .module('statusApp') .controller('StatusController', StatusController); function StatusController($rootScope, Status, md5) { var vm = this; vm.addStatus = addStatus; vm.md5 = md5; vm.statusData = Status; function addStatus() { if(vm.statusText) { vm.statusData.$add({ // Add the status data to Firebase date: Firebase.ServerValue.TIMESTAMP, text: vm.statusText, user: { username: $rootScope.loggedInUserData.username, email: $rootScope.loggedInUserData.email } }); vm.statusText = ''; } } } })(); 

Мы можем получить все наши данные о состоянии в виде массива, просто позвонив в службу Status и назначив этот вызов ключу, что мы и сделали с помощью vm.statusData = Status . Теперь мы сможем выполнить ng-repeat для этих данных в нашем представлении, которое мы увидим далее.

Мы хотим, чтобы изображения Gravatar для наших пользователей отображались рядом с обновлениями их статуса, и для этого потребуется хэшировать их адреса электронной почты. Мы позаботимся обо всем этом прямо с точки зрения простоты, но для этого нам понадобится доступ к Angular MD5 в шаблоне. Это достигается установкой vm.md5 = md5 .

В нашем методе addStatus мы сначала проверяем, существует ли запись состояния из представления, и если это так, мы используем метод $add AngularFire, чтобы добавить запись в хранилище данных. Мы передаем объект с некоторыми дополнительными данными, включая дату, которая равна фактической отметке времени на сервере. Важно, чтобы мы использовали временную метку сервера Firebase, поскольку это «официальное» время записи записи. Если бы мы полагались на собственную временную метку пользователя с его компьютера, небольшие задержки при отправке данных по проводам означали бы неточности в реальном времени записи данных, что впоследствии могло привести к искажению данных.

Вы увидите, что в объекте user переданном методу $add , мы устанавливаем username и ключ email которые получают свои данные из $rootScope . Мы еще не настроили $rootScope для этого, но мы сделаем это в следующем разделе.

Наконец, после добавления статуса мы vm.statusText поле vm.statusText .

Теперь, когда контроллер установлен, давайте перейдем к шаблону.

 <!-- components/status/statusView.html --> <md-input-container> <label>Status</label> <textarea ng-model="status.statusText" type="text"></textarea> </md-input-container> <md-button class="md-raised md-warn" ng-click="status.addStatus()">Post</md-button> <md-content> <md-list> <md-list-item class="md-3-line" ng-repeat="statusItem in status.statusData | orderBy:'-date'"> <img ng-src="http://www.gravatar.com/avatar/{{status.md5.createHash(statusItem.user.email)}}" class="face" alt="{{statusItem.user.username}}"> <div class="md-list-item-text"> <h3>{{statusItem.user.username}}</h3> <span>{{statusItem.date | date:'mediumDate'}}</span> <p>{{statusItem.text}}</p> </div> <md-divider md-inset></md-divider> </md-list-item> </md-list> </md-content> 

В верхней части окна у нас есть текстовая область и кнопка отправки, чтобы наши пользователи могли регистрировать свои статусы. Мы устанавливаем ng-model равным нашему statusText и statusText ng-click по кнопке submit, чтобы равняться addStatus

Для отображения сохраненных статусов мы используем элемент md-list-item Angular Material и устанавливаем для него ng-repeat для циклического перемещения по массиву статусов. Здесь вы увидите, что мы упорядочиваем по дате, но в обратном порядке, поэтому мы получаем последние статусы вверху. Для этого мы можем просто поставить отрицательный знак перед датой, поэтому мы получаем orderBy:'-date' .

Чтобы получить изображения Gravatar для наших пользователей, нам просто нужно установить ng-src тега img в домен Gravatar и добавить в конце хеш-адрес электронной почты пользователя. Поскольку у нас есть ссылка на Angular MD5 в контроллере, теперь мы можем использовать ее в представлении. Мы вызываем метод createHash и передаем адрес электронной почты пользователя для генерации хэша.

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

Снимок экрана 4 приложения состояния в реальном времени

Добавление текущего пользователя в $ rootScope

Как мы отмечали ранее, для addStatus метода addStatus нам нужно добавить некоторые свойства в $rootScope которые ссылаются на данные для текущего вошедшего в систему пользователя. Мы можем сделать это в методе run в нашем файле app.js , используя прослушиватель событий $on Angular с событием $stateChangeStart которое поставляется с UI Router. По сути, мы хотим получить данные для нашего вошедшего в систему пользователя из конечной точки /users мы настроили ранее, которая заполняется при регистрации нового пользователя. Для выполнения этого шага мы будем использовать несколько методов, которые мы видели ранее в сервисе User .

 //app.js (function() { 'use strict'; angular .module('statusApp', ['firebase', 'ngMaterial', 'angular-md5', 'ui.router']) .config(function($stateProvider, $urlRouterProvider) { // If a route other than status is requested, // go to the auth route $urlRouterProvider.otherwise('/auth'); $stateProvider .state('auth', { url: '/auth', templateUrl: 'components/auth/authView.html', controller: 'AuthController as auth' }) .state('status', { url: '/status', templateUrl: 'components/status/statusView.html', controller: 'StatusController as status' }); }) .run(function($rootScope, $state, User) { // Listen for changes to the state and run the code // in the callback when the change happens $rootScope.$on('$stateChangeStart', function() { // Use the User service to get the currently // logged-in user from local storage var loggedInUser = User.getLoggedInUser(); // Check that we actually have a logged-in user // saved in local storage if(loggedInUser) { // Use the getUserData method on the User service // to grab the data from the /users endpoint in // Firebase for the logged-in user $rootScope.loggedInUserData = User.getUserData(loggedInUser.uid); } }); }); })(); 

В методе run мы отслеживаем изменения состояния приложения, например, после того, как пользователь входит в систему или регистрируется и перенаправляется в status состояния. Когда это происходит, мы хотим использовать службу User чтобы получить текущего пользователя, вошедшего в систему, который использует данные, которые Firebase хранит в локальном хранилище для пользователя с ключом firebase:session::statusapp . Если там хранятся данные, мы хотим вызвать метод getUserData в сервисе User и передать uid для нашего вошедшего в систему пользователя. Данные, возвращаемые этим вызовом, затем помещаются в свойство $rootScope которое позволяет нам обращаться к нему через приложение.

Теперь, когда у нас есть данные текущего пользователя в $rootScope , мы можем получить к ним доступ в StatusController чтобы при обновлении статуса пользователь сохранял свое имя пользователя и электронную почту вместе со своим статусом.

Удаление статусов

Последнее, что мы хотим сделать здесь, это дать зарегистрированному пользователю возможность удалять свои собственные статусы. Для этого мы можем использовать метод $remove , предоставляемый AngularFire. Давайте создадим новый метод в нашем StatusController который будет обрабатывать удаление.

 // components/status/statusController.js (function() { 'use strict'; angular .module('statusApp') .controller('StatusController', StatusController); function StatusController($rootScope, Status, md5) { var vm = this; vm.addStatus = addStatus; vm.deleteStatus = deleteStatus; vm.md5 = md5; vm.statusData = Status; function addStatus() { if(vm.statusText) { // Add the status data to Firebase vm.statusData.$add({ date: Firebase.ServerValue.TIMESTAMP, text: vm.statusText, user: { username: $rootScope.loggedInUserData.username, email: $rootScope.loggedInUserData.email } }); vm.statusText = ''; } } function deleteStatus(status) { // Remove the status that was passed in // from the views vm.statusData.$remove(status); } } })(); 

Мы добавили метод vm.deleteStatus который ссылается на недавно определенную функцию deleteStatus . Это примет статус и использует $remove AngularFire, чтобы удалить его из Firebase, и автоматически обновит представление, чтобы отразить удаление. С этим методом нам нужно использовать его в представлении.

 <!-- components/status/statusView.html --> ... <md-content> <md-list> <md-list-item class="md-3-line" ng-repeat="statusItem in status.statusData | orderBy:'-date'"> <img ng-src="http://www.gravatar.com/avatar/{{status.md5.createHash(statusItem.user.email)}}" class="face" alt="{{statusItem.user.username}}"> <div class="md-list-item-text"> <h3>{{statusItem.user.username}}</h3> <span>{{statusItem.date | date:'mediumDate'}}</span> <p>{{statusItem.text}}</p> </div> <md-divider md-inset></md-divider> <md-icon class="remove-status" ng-if="statusItem.user.username === loggedInUserData.username" ng-click="status.deleteStatus(statusItem)"> X </md-icon> </md-list-item> </md-list> </md-content> 

Здесь вы увидите, что мы добавили новый элемент md-icon в представление. Директива ng-if говорит, что мы хотим, чтобы этот элемент был включен, только если имя пользователя статуса совпадает с именем пользователя, вошедшего в систему в данный момент. Таким образом, возможность удаления статуса отображается только владельцу этого статуса. Мы устанавливаем ng-click для метода deleteStatus который мы создали в StatusController и передаем текущий statusItem . Теперь, когда пользователь нажимает X, этот статус будет удален.

Снимок экрана 1 приложения состояния в реальном времени

Добавление собственной учетной записи Firebase

Получить собственную учетную запись Firebase, работая с приложением статуса, очень легко. Сначала вам нужно зарегистрироваться в Firebase, что даст вам доступ к бесплатному стартовому уровню. После того, как вы зарегистрировались, добавьте приложение, выбрав «Создать новое приложение» на своей панели инструментов и присвойте ему любое имя. Затем вам нужно включить простую аутентификацию, выбрав «Управление приложением», затем «Логин и авторизация» на боковой панели и отметив флажок «Включить аутентификацию по электронной почте и паролю». Наконец, вам нужно изменить имя учетной записи Firebase, с которой приложение связывается, поменяв statusapp на имя вашего приложения в трех разных файлах:

  • компоненты / авт / authService.js
  • компоненты / статус / statusService.js
  • компоненты / пользователь / userService.js

Примечание о безопасности

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

Правила Firebase написаны на JSON и могут быть определены на вкладке «Безопасность и правила» на панели инструментов приложения. Чтобы узнать больше о правилах Firebase и о том, как их реализовать в вашем приложении, прочитайте о User Based Security .

Завершение

В этом уроке мы увидели, как собрать приложения AngularJS и Firebase, используя AngularFire и Angular Material для стилизации. Мы сосредоточились на аутентификации приложения, а также на том, как создавать и удалять пользовательские статусы.

Надеюсь, это будет полезно для вас, когда придет время реализовать Firebase для вашего следующего проекта. Я хотел бы услышать о том, что вы работаете в комментариях!