3 октября 2017 года Google объявил о выпуске еще одной службы баз данных в реальном времени на Firebase, известной как Firestore. Теперь у Google уже была служба базы данных в реальном времени, известная как Firebase Realtime Db, так зачем выпускать новый продукт, который предлагает те же услуги, что и уже существующий?

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

В этой статье мы собираемся создать простое приложение TODO с Angular, которое использует Firestore для (C) reate, (R) ead, (U) pdate и (D) elete TODO. Наше приложение также извлечет выгоду из всех замечательных функций, которые предлагает Firestore, например синхронизация данных в реальном времени, автономные возможности и удобное обнаружение изменений.

Хорошая новость в том, что команда Angular уже разработала библиотеку, известную как AngularFire, которая предлагает удобный API для взаимодействия с Firestore. Достаточно сказать, время повеселиться с Firestore

Настройка Firestore

Создать новый проект Firebase

Войдите в консоль Firebase на сайте firebase.google.com и создайте новый проект, нажав кнопку Добавить проект.

Введите необходимые данные для вашего проекта

Создайте новое приложение в рамках проекта

Нажмите ссылку Добавить другое приложение и выберите Добавить Firebase в свое веб-приложение.

При выборе этой опции появится конфигурация приложения firebase, скопируйте объект конфигурации, он нам понадобится позже.

Создать новую базу данных firestore

Теперь прокрутите страницу консоли вниз и нажмите Начало работы на вкладке База данных.

На следующей странице представлены два варианта базы данных Firebase в реальном времени. Выберите вариант Cloud Firestore.

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

Теперь вам будет представлена ​​панель управления вашей базы данных firestore, нажмите ссылку Добавить коллекцию и введите необходимые данные, как показано ниже.

На следующем слайде диалогового окна предлагается добавить первый документ. В Firestore база данных представлена ​​как коллекция (аналогично концепции коллекций в javascript). Эти коллекции содержат отдельные документы, которые представляют каждую часть данных, хранящихся в базе данных.

Документ - это просто объект, вы можете добавить столько полей, сколько хотите, но для этого проекта просто введите описание в Поле, оставьте Тип в виде строки и введите Задачу 1 (или что-то еще) в текстовое поле значения.

Большой! Это все, что нам нужно для настройки базы данных.

Создание приложения TODO

Чтобы начать проект, я создал начальный проект, чтобы начать процесс и избавить вас от стресса, связанного с проектированием пользовательского интерфейса. Просто клонируйте проект здесь. Завершенный проект находится в ветке master, а начальная точка находится в ветви start, поэтому для начала переключитесь на ветвь start.

Настроить firebase

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

Создайте app.config.ts и app.model.ts

Внутри папки приложения создайте эти два файла: app.config.js для хранения некоторых пользовательских конфигураций приложения и app.model.ts для хранения интерфейса, определяющего наши модель данных.

app.config.js

export const config = {
   collection_endpoint: “tasks”
};

app.model.ts

export interface Task {
    id: string;
    description: string;
}

Большой! Затем мы создадим сервис для абстрагирования всех наших операций с Firestore.

TasksService

Создайте app.service.ts в папке приложения, выполнив команду angular-cli.

ng g s app

Наш сервис будет содержать 3 функции помимо конструктора. Этими функциями будут addTask, updateTask и deleteTask .

Чтобы начать создание сервиса, нам нужно сначала импортировать необходимые модули.

import { config } from “./app.config”;
import { Task } from “./app.model”;
import { Injectable } from “@angular/core”;
import {
  AngularFirestoreDocument,
  AngularFirestore,
  AngularFirestoreCollection
} from “angularfire2/firestore”;

Затем мы создаем два члена класса: tasks и taskDoc.

tasks: AngularFirestoreCollection<Task>;
private taskDoc: AngularFirestoreDocument<Task>;

Затем мы получаем ссылку на нашу базу данных в конструкторе службы.

constructor(private db: AngularFirestore) {
   //Get the tasks collection
   this.tasks = db.collection<Task>(config.collection_endpoint);
}

В нашей функции addTask мы просто берем объект task и вызываем метод add для ссылки на нашу базу данных.

addTask(task) {
  //Add the new task to the collection
  this.tasks.add(task);
} //addTask

Наш метод updateTask будет принимать идентификатор документа и обновлять объект в качестве аргументов, в этом методе мы получаем ссылку на документ и вызываем update работать на нем

updateTask(id, update) {
   //Get the task document
   this.taskDoc = this.db.doc<Task>(`${config.collection_endpoint}/${id}`);
   this.taskDoc.update(update);
} //updateTask

Метод deleteTask принимает идентификатор документа и получает ссылку на документ, а затем вызывает для него функцию удаления.

deleteTask(id) {
   //Get the task document
   this.taskDoc = this.db.doc<Task>(`${config.collection_endpoint}/${id}`);
   //Delete the document
   this.taskDoc.delete();
} //deleteTask

Большой! Наша служба завершена.

Привязка коллекции базы данных к шаблону компонента

Теперь давайте прочитаем нашу базу данных и отобразим хранящиеся в ней задачи в нашем шаблоне. Сначала мы импортируем модуль AngularFirestore в app.component.ts.

import { AngularFirestore } from “angularfire2/firestore”;

Затем мы вставляем ссылку на базу данных и службу в наш конструктор.

constructor(private db: AngularFirestore, private taskService: TaskService)

Теперь нам нужно создать переменную-член tasks и связать ее с нашей коллекцией внутри ngOnInit, убедившись, что ваш компонент реализует интерфейс OnInit.

tasks: Observable<any[]>;

ngOnInit() {
this.tasks = this.db.collection(config.collection_endpoint).valueChanges();
}

Теперь привязка к коллекции таким образом хороша, но не даст нам доступа к идентификатору документа, который потребуется для управления документом (например, обновления или удаления документа). Таким образом, вместо использования метода valueChanges () мы будем использовать snapshotChanges (), который проверяет наличие изменений и дает нам доступ не только к документам коллекции, но и к их метаданные. Мы используем его для доступа к идентификатору документа и прикрепляем его к возвращенному документу.

this.tasks = this.db
.collection(config.collection_endpoint)
.snapshotChanges()
.map(actions => {
   return actions.map(a => {
     //Get document data
     const data = a.payload.doc.data() as Task;
     //Get document id
     const id = a.payload.doc.id;
     //Use spread operator to add the id to the document data
     return { id, …data };
   });
});

Потрясающие! Теперь мы можем привязать наши задачи к нашему списку в представлении app.component.html с помощью конвейера async.

<tr *ngFor=”let task of tasks | async; let i = index” [attr.data-index]=”i”>
   <td>{{i + 1}}</td>
   <td>{{task.description}}</td>
</tr>

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

Далее необходимо добавить в компонент функции saveTask, edit и deleteTask.

Сначала мы добавляем еще 3 переменные-члены в класс компонента.

myTask: string;
editMode: boolean = false;
taskToEdit: any = {};

Затем мы добавляем наши функции

изменить

edit(task) {
  console.log(task);
  //Set taskToEdit and editMode
  this.taskToEdit = task;
  this.editMode = true;
  //Set form value
  this.myTask = task.description;
} //edit

saveTask

saveTask() {
   if (this.myTask !== null) {
      //Get the input value
      let task = {
         description: this.myTask
      };
      if (!this.editMode) {
         console.log(task);
         this.taskService.addTask(task);
      } else {
         //Get the task id
         let taskId = this.taskToEdit.id;
         //update the task
         this.taskService.updateTask(taskId, task);
      }
      //set edit mode to false and clear form
      this.editMode = false;
      this.myTask = “”;
   }
} //saveTask

deleteTask

deleteTask(task) {
   //Get the task id
   let taskId = task.id;
   //delete the task
   this.taskService.deleteTask(taskId);
} //deleteTask

Затем мы привязываем эти функции и переменные-члены к нашему шаблону, форме и списку.

<form #f=”ngForm”>
  <div class=”form-group”>
  <input [(ngModel)]=”myTask” name=”myTask” type=”text” class=”form-control” placeholder=”Enter Task” required>
  </div>
  <p *ngIf=”loading”>
     <i class=”fa fa-spinner fa-spin”></i>
  </p>
  <div class=”form-group”>
   <button class=”btn btn-primary” [disabled]=”!f.valid” (click)=”saveTask()”>
     Save Task
   </button>
  </div>
</form>

список

<td>
  <button class=”btn btn-success” (click)=”edit(task)”>
    <i class=”fa fa-edit”></i>
  </button>
  <button class=”btn btn-danger” (click)=”deleteTask(task)”>
    <i class=”fa fa-remove”></i>
  </button>
</td>

Потрясающе !, просто протестируйте приложение, сохранив задачу, щелкнув задачу, чтобы обновить ее, и нажав красную кнопку, чтобы удалить задачу.

Все работает? Большой!. Если нет, просмотрите завершенный проект, чтобы увидеть, что вы, возможно, пропустили.

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

Для получения дополнительной информации о Firestore посетите документацию здесь, для получения дополнительной информации об AngularFire ознакомьтесь с документацией здесь.

Удачного кодирования!