От автора: этот пост является частью серии статей «Создание приложения для блоггинга с использованием Angular и MongoDB». В предыдущей части серии вы узнали, как создать ShowPostComponent для отображения на главной странице списка постов блога. Мы извлекли записи, которые были вставлены из оболочки MongoDB, используя созданную конечную точку API REST. В этой части мы создадим новый компонент под названием AddPostComponent, с помощью которого будет происходить добавление поста в блог пользователем.
Приступим. Давайте начнем с клонирования исходного кода из предыдущих частей серии.
git clone https://github.com/royagasthyan/ShowPost AddPost
Перейдите в каталог проекта и установите необходимые зависимости.
cd AddPost/client npm install cd AddPost/server npm install
После установки зависимостей перезапустите клиентское и серверное приложение.
cd AddPost/client npm start cd AddPost/server node app.js
Откройте в браузере адрес http://localhost:4200, и у вас должно запуститься приложение.
Создание компонента Add Post
Давайте начнем с создания AddPostComponent. Создайте в папке src/app папку с именем add-post. В папке add-post создайте файл с именем add-post.component.ts и добавьте в него следующий код:
import { Component } from '@angular/core'; import { Post } from '../models/post.model'; @Component({ selector: 'app-add-post', templateUrl: './add-post.component.html', styleUrls: ['./add-post.component.css'] }) export class AddPostComponent { constructor() { } }
Создайте файл add-post.component.html и добавьте в него следующий код HTML:
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="exampleModalLabel">Modal title</h5> <button type="button" #closeBtn class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <form> <div class="form-group"> <label for="exampleInputEmail1">Title</label> <input name="title" type="text" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter title"> </div> <div class="form-group"> <label for="exampleInputPassword1">Description</label> <textarea name="description" class="form-control" id="exampleInputPassword1" placeholder="Password"> </textarea> </div> <button type="button" class="btn btn-primary">Add</button> </form> </div> </div> </div> </div>
Компонент добавления постов будет отображаться во всплывающем окне. Теперь вам нужно добавить AddPostComponent в NgModule. Импортируйте AddPostComponent в файл app.module.ts.
import { AddPostComponent } from './add-post/add-post.component';
Добавьте компонент в список объявлений NgModule следующим образом:
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { ROUTING } from './app.routing'; import { FormsModule } from '@angular/forms'; import { HttpClientModule } from '@angular/common/http'; import { RootComponent } from './root/root.component'; import { LoginComponent } from './login/login.component'; import { HomeComponent } from './home/home.component'; import { ShowPostComponent } from './show-post/show-post.component'; import { AddPostComponent } from './add-post/add-post.component'; @NgModule({ declarations: [ RootComponent, LoginComponent, HomeComponent, ShowPostComponent, AddPostComponent ], imports: [ BrowserModule, ROUTING, FormsModule, HttpClientModule ], providers: [], bootstrap: [RootComponent] }) export class AppModule { }
Чтобы активировать всплывающее окно добавления постов мы уже добавили к кнопке атрибут data-target в файле home.component.html.
<button type="button" class="btn btn-link" data-toggle="modal" data-target="#exampleModal"> Add </button>
Сохраните указанные выше изменения и перезапустите приложение. Войдите в приложение и нажмите ссылку Add на главной странице. У вас во всплывающем окне отобразится компонент AddPostComponent.
Включение функции добавления постов
Добавьте директиву ngModel к элементам ввода для title и description.
<input name="title" type="text" [(ngModel)]="post.title" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter title"> <textarea name="description" [(ngModel)]="post.description" class="form-control" id="exampleInputPassword1" placeholder="Password"> </textarea>
Добавьте к кнопке директиву click для вызова метода сохранения поста.
<button (click)="addPost()" type="button" class="btn btn-primary">Add</button>
Импортируйте модель Post из src/app/models/post.model.ts в файл add-post.component.ts.
import { Post } from '../models/post.model';
Определите переменную post в файле add-post.component.ts.
public post : Post;
Определите в файле add-post.component.ts метод addPost. Из метода addPost мы будем осуществлять валидацию введенных заголовка и описания и выполнять вызов метода службы для вызова REST API. Вот как будет выглядеть метод:
addPost() { if(this.post.title && this.post.description){ // вызов метода службы для добавления постов } else { alert('Title and Description required'); } }
Давайте создадим файл службы для компонента AddPostComponent. Создайте файл с именем add-post.service.ts и добавьте в него следующий код:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Post } from '../models/post.model'; @Injectable() export class AddPostService { constructor(private http: HttpClient){ } }
В AddPostService создайте метод addPost, чтобы выполнить вызов REST API.
addPost(post: Post){ return this.http.post('/api/post/createPost',{ title : post.title, description : post.description }) }
Как видно из приведенного выше кода, мы использовали HttpClient для вызова API и возврата Observable. В файле add-post.component.ts внутри метода addPost вы осуществим подписку на метод addPost из файла add-post.service.ts.
this.addPostService.addPost(this.post).subscribe(res =>{ // ответ от вызова REST API });
Вот как выглядит файл add-post.component.ts:
import { Component } from '@angular/core'; import { AddPostService } from './add-post.service'; import { Post } from '../models/post.model'; @Component({ selector: 'app-add-post', templateUrl: './add-post.component.html', styleUrls: ['./add-post.component.css'], providers: [ AddPostService ] }) export class AddPostComponent { public post : Post; constructor(private addPostService: AddPostService) { this.post = new Post(); } addPost() { if(this.post.title && this.post.description){ this.addPostService.addPost(this.post).subscribe(res =>{ console.log('response is ', res) }); } else { alert('Title and Description required'); } } }
Создание REST API для добавления постов
Давайте создадим конечную точку REST API для добавления постов в MongoDB. В файле server/app.js создайте конечную точку API, как показано ниже:
app.post('/api/post/createPost', (req, res) => { // добавляем данные в MongoDB })
Во-первых, вам нужно подключиться к базе данных MongoDB с помощью клиента Mongoose.
mongoose.connect(url, { useMongoClient: true }, function(err){ if(err) throw err; console.log('connection established '); });
После установления соединения вам необходимо создать объект модели, используя схему Post, определенную в файле server/model/post.js.
const post = new Post({ title: req.body.title, description: req.body.description })
Как видно из приведенного выше кода, мы создали объект Post, используя title и description, переданные из объекта запроса req. Вызовите метод сохранения объекта Post для сохранения поста в MongoDB.
post.save((err, doc) => { if(err) throw err; return res.status(200).json({ status: 'success', data: doc }) })
Как видно из приведенного выше кода, после вызова обратного вызова метода save без ошибки он возвращает сообщение об успешном завершении вместе с объектом doc. Вот как выглядит конечная точка REST API:
app.post('/api/post/createPost', (req, res) => { mongoose.connect(url, { useMongoClient: true }, function(err){ if(err) throw err; const post = new Post({ title: req.body.title, description: req.body.description }) post.save((err, doc) => { if(err) throw err; return res.status(200).json({ status: 'success', data: doc }) }) }); })
Сохраните приведенные выше изменения и перезапустите как сервер Angular, так и Node. Войдите в приложение и попробуйте добавить новый пост. После того, как вы нажмете кнопку Add, проверьте консоль браузера, и вы получите ответ об успешном выполнении операции.
Когда данные успешно добавлены в базу данных, нам необходимо закрыть всплывающее окно. Чтобы закрыть всплывающее окно, существует кнопка закрытия, которую нужно нажать программно. Мы будете использовать декоратор @ViewChild для доступа к кнопке закрытия. Импортируйте ViewChild и ElementRef в AddPostComponent.
import { Component, ViewChild, ElementRef } from '@angular/core';
Внутри компонента AddPostComponent определите следующую переменную:
@ViewChild('closeBtn') closeBtn: ElementRef;
Инициируйте клик closeBtn, используя следующий код:
this.closeBtn.nativeElement.click();
Добавьте вышеприведенный код в обратный вызов метода addPost. Ниже приведен метод addPost из add-post.component.ts.
addPost() { if(this.post.title && this.post.description){ this.addPostService.addPost(this.post).subscribe(res =>{ this.closeBtn.nativeElement.click(); }); } else { alert('Title and Description required'); } }
Сохраните изменения и перезапустите клиентский сервер. Войдите в приложение и попробуйте добавить в блог новый пост. После того, как данные в блоге успешно сохранены, всплывающее окно закроется.
Обновление списка блога
Следует отметить, что недавно добавленное сообщение в блоге не отображается в списке постов блога. Поэтому нам нужно добавить триггер для уведомления, когда нужно обновлять ShowPostComponent. Мы будем использовать для связи между этими двумя компонентами общий сервис. Создайте в папке src/app папку service. Создайте в ней файл common.service.ts со следующим кодом:
import { Injectable } from '@angular/core'; import { Subject } from 'rxjs/Subject'; @Injectable() export class CommonService { public postAdded_Observable = new Subject(); constructor(){ } notifyPostAddition(){ this.postAdded_Observable.next(); } }
Как видно из приведенного выше кода, мы объявили объект с именем postAdded_Observable для отслеживания добавления нового поста в базу данных. Каждый раз, когда в базу данных добавляется новый пост, мы вызываете метод notifyPostAddition, который будет уведомлять подписчиков об обновлении. Импортируйте CommonService в app.module.ts и включите его в список провайдеров NgModule. Вот как это выглядит:
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { ROUTING } from './app.routing'; import { FormsModule } from '@angular/forms'; import { HttpClientModule } from '@angular/common/http'; import { RootComponent } from './root/root.component'; import { LoginComponent } from './login/login.component'; import { HomeComponent } from './home/home.component'; import { ShowPostComponent } from './show-post/show-post.component'; import { AddPostComponent } from './add-post/add-post.component'; import { CommonService } from './service/common.service'; @NgModule({ declarations: [ RootComponent, LoginComponent, HomeComponent, ShowPostComponent, AddPostComponent ], imports: [ BrowserModule, ROUTING, FormsModule, HttpClientModule ], providers: [CommonService], bootstrap: [RootComponent] }) export class AppModule { }
Импортируйте CommonService в файл show-post.component.ts и инициализируйте его в методе конструктора.
import { CommonService } from '../service/common.service'; constructor(private showPostService: ShowPostService, private commonService: CommonService) { }
Внутри метода ngOnInit подпишитесь на переменную postAdded_Observable и загрузите метод getAllPost. Вот как будет выглядеть метод ngOnInit:
ngOnInit(){ this.getAllPost(); this.commonService.postAdded_Observable.subscribe(res => { this.getAllPost(); }); }
Импортируйте CommonService в файл add-post.component.ts и вызовите после добавления поста в блоге метод notifyPostAddition. Вот как выглядит метод addPost из AddPostComponent:
addPost() { if(this.post.title && this.post.description){ this.addPostService.addPost(this.post).subscribe(res =>{ this.closeBtn.nativeElement.click(); this.commonService.notifyPostAddition(); }); } else { alert('Title and Description required'); } }
Сохраните указанные выше изменения и перезапустите клиентский сервер. Войдите в приложение и добавьте в блог новый пост. После этого список постов обновится, и в нем появится только что добавленная запись.
Заключение
В этом руководстве мы создали AddPostComponent, чтобы добавить данные о посте в базу данных MongoDB. Мы создали REST API для сохранения постов в MongoDB с использованием клиента Mongoose. В следующей части серии мы реализуем функционал для редактирования и обновления постов. Исходный код этого руководства доступен на GitHub.
Автор: Roy Agasthyan
Источник: https://code.tutsplus.com/
Редакция: Команда webformyself.