Database와 front end를 연결하기 위한 파일들을 구현하였으면, 이제 프론트엔드를 구현해보겠다.
*코드는 entity 명령어를 사용해서 생성된 게시판을 참고하였다.
먼저, NavBar에서 Board를 눌렀을 때, DB에 저장된 Board 정보들을 가져와 출력하는 화면을 만들어보겠다.
현재, NavBar에서 Board를 누르면, app-routing.module을 통해 BoardModule을 호출한다.
BoardModule에서 BoardRoute를 호출한다. 아무 path도 주지 않을 경우, BoardComponent가 호출된다. BoardComponent에서 기본 화면(DB에 저장된 모든 Board정보들을 출력)이 보여져야한다.
BoardComponent의 화면은 board.component.html이기 때문에, 먼저 html 파일을 구현해주겠다.
//board.component.html
<div>
<h2 id="page-heading">
<span>Boards</span>
<button id="jh-create-entity" class="btn btn-primary float-right jh-create-entity create-book" [routerLink]="['/board/new']">
<fa-icon [icon]="'plus'"></fa-icon>
<span >
Create a new Board
</span>
</button>
</h2>
<jhi-alert-error></jhi-alert-error>
<jhi-alert></jhi-alert>
<br/>
<div class="alert alert-warning" *ngIf="boards?.length === 0">
<span>No books found</span>
</div>
<div class="table-responsive" *ngIf="books?.length > 0">
<table class="table table-striped" aria-describedby="page-heading">
<thead>
<tr>
<th scope="col" ><span>ID</span></th>
<th scope="col" ><span>Title</span></th>
<th scope="col" ><span>Contents</span></th>
<th scope="col" ><span>Created Date</span></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let board of boards ;trackBy: trackId">
<td><a [routerLink]="['/board', board.id, 'view' ]">{{board.id}}</a></td>
<td>{{board.title}}</td>
<td>{{board.contents}}</td>
<td>{{board.publicationDate | date:'mediumDate'}}</td>
<td class="text-right">
<div class="btn-group">
<button type="submit"
[routerLink]="['/board', board.id, 'view' ]"
class="btn btn-info btn-sm">
<fa-icon [icon]="'eye'"></fa-icon>
<span class="d-none d-md-inline">View</span>
</button>
<button type="submit"
[routerLink]="['/board', board.id, 'edit']"
class="btn btn-primary btn-sm">
<fa-icon [icon]="'pencil-alt'"></fa-icon>
<span class="d-none d-md-inline">Edit</span>
</button>
<button type="submit"
[routerLink]="['/board', { outlets: { popup: board.id + '/delete'} }]"
replaceUrl="true"
queryParamsHandling="merge"
class="btn btn-danger btn-sm">
<fa-icon [icon]="'times'"></fa-icon>
<span class="d-none d-md-inline">Delete</span>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
이 상태로는 코드의 'boards'와 'trackId'를 인식하지 못한다. board.component.ts 파일에 선언해 주어야한다.
//board.component.ts
import { Component, OnInit} from '@angular/core';
import { IBoard } from "app/shared/model/board.model";
@Component({
selector: 'jhi-board',
templateUrl: './board.component.html',
styleUrls: ['./board.component.scss']
})
export class BoardComponent implements OnInit {
boards: IBoard[];
constructor() {}
ngOnInit() {
}
trackId(index: number, item: IBoard) {
return item.id;
}
}
IBoard는 ... app -> shared -> model 안에 만들어준다.
//board.model.ts
import {Moment} from "moment";
export interface IBoard {
id?: number;
title?: string;
contents?: string;
createdDate?: Moment;
}
export class Board implements IBoard {
constructor(
public id?: number,
public title?: string,
public contents?: string,
public createdDate?: Moment
) {}
}
crud기능을 위한 service를 BoardComponent의 생성자에 선언해 준다.
//board.component.ts
import { Component, OnInit} from '@angular/core';
import { IBoard } from "app/shared/model/board.model";
import {BoardService} from "app/board/board.service";
@Component({
selector: 'jhi-board',
templateUrl: './board.component.html',
styleUrls: ['./board.component.scss']
})
export class BoardComponent implements OnInit {
boards: IBoard[];
constructor(
protected boardService: BoardService
) {}
ngOnInit() {
}
}
BoardComponent에서 사용하기 위해, board.service.ts를 구현해준다. 여기서 http 통신으로 BoardResource 파일로 연결시켜준다.
//board.service.ts
import { Injectable } from '@angular/core';
import {HttpClient, HttpResponse} from "@angular/common/http";
import {IBoard} from "app/shared/model/board.model";
import {SERVER_API_URL} from "app/app.constants";
import {Observable} from "rxjs";
import {createRequestOption} from "app/shared/util/request-util";
type EntityResponseType = HttpResponse<IBoard>;
type EntityArrayResponseType = HttpResponse<IBoard[]>;
@Injectable({
providedIn: 'root'
})
export class BoardService {
public resourceUrl = SERVER_API_URL + 'api/boards';
constructor(protected http: HttpClient) { }
query(req?: any): Observable<EntityArrayResponseType>{
const options = createRequestOption(req);
return this.http.get<IBoard[]>(this.resourceUrl, {params: options, observe: 'response'});
}
}
컴포넌트에 처음 시작 시 loadAll을 통해 모든정보를 불러온다.
//board.component.ts
import { Component, OnInit} from '@angular/core';
import { IBoard } from "app/shared/model/board.model";
import { filter, map } from 'rxjs/operators';
import {BoardService} from "app/board/board.service";
import {HttpResponse} from "@angular/common/http";
@Component({
selector: 'jhi-board',
templateUrl: './board.component.html',
styleUrls: ['./board.component.scss']
})
export class BoardComponent implements OnInit {
boards: IBoard[];
constructor(
protected boardService: BoardService
) {}
loadAll(){
this.boardService
.query()
.pipe(
filter((res:HttpResponse<IBoard[]>)=>res.ok),
map((res:HttpResponse<IBoard[]>)=>res.body)
)
.subscribe((res: IBoard[])=>{
this.boards = res;
});
}
ngOnInit() {
this.loadAll(); //처음 실행시 시작되는 것
}
}
만약 db에 변경이 생기면 새로 로드해주어야하는데 그 기능을 registerChangeInBoards 메소드로 구현해보겠다. 'boardListModification' 이라는 값을 받게되면, 목록을 새로 로드해준다.
//board.component.ts
//...
@Component({
selector: 'jhi-board',
templateUrl: './board.component.html',
styleUrls: ['./board.component.scss']
})
export class BoardComponent implements OnInit, OnDestroy {
boards: IBoard[];
eventSubscriber: Subscription;
constructor(protected boardService: BoardService, protected eventManager: JhiEventManager) {}
loadAll() {
this.boardService
.query()
.pipe(
filter((res: HttpResponse<IBoard[]>) => res.ok),
map((res: HttpResponse<IBoard[]>) => res.body)
)
.subscribe((res: IBoard[]) => {
this.boards = res;
});
}
ngOnInit() {
this.loadAll();
this.registerChangeInBoards();
}
trackId(index: number, item: IBoard) {
return item.id;
}
ngOnDestroy() {
this.eventManager.destroy(this.eventSubscriber);
}
registerChangeInBoards() {
this.eventSubscriber = this.eventManager.subscribe('boardListModification', response => this.loadAll());
}
}
로그인 후 접속해보면, 아래와 같이 출력된다. 현재 정보가 없기 때문에 No books found가 출력된다.
workbench를 통해, 테스트 값을 넣어주면, 아래와 같이 잘 출력됨을 볼 수 있다.