서비스 구현
먼저 Rest API 로 할일 추가를 테스트하고 결과를 확인한다.
HttpClient.post( url: string, body: any | null, options?: {headers?: HttpHeaders | {[p: string]: string | string[]}, observe?: “body”, params?: HttpParams | {[p: string]: string | string[]}, reportProgress?: boolean, responseType?: “json”, withCredentials?: boolean}): Observable<T>
첫번째 파라메터 url은 string 타입,
두번째 파라메터 body는 Request body에 보내는 데이터이다. any 타입 혹은 null이 허용된다.
세번째 파라메터는 json 객체이다. body에 보내는 데이터가 json 데이터라는걸 명시하기 위해서 Content-Type을 헤더에 추가한다.
1 2 3 4 5 |
addTodo(todo: TodoVo): Observable<TodoVo> { const headers = new HttpHeaders(); headers.append('Content-Type', 'application/json'); return this.http.post<TodoVo>(environment.HOST + '/api/todo', todo, {headers: headers}); } |
모델 데이터 생성
새로운 할일은 하나의 TodoVo 객체이므로 TodoVo객체 타입의 변수를 하나 선언하고 뷰에 바인딩한다.
1 |
newTodo = new TodoVo(); |
그리고, view에 바인딩한다.
1 2 3 4 5 6 7 8 9 10 11 |
<div class="row"> <div class="col-sm-8"> <div class="form-group"> <input type="text" class="form-control" placeholder="할일을 입력하세요." [(ngModel)]="newTodo.todo"> </div> </div> <div class="col-sm-4"> <button class="btn btn-primary btn-block" (click)="addTodo()">추가</button> </div> </div> |
추가 버튼을 클릭시 서비스를 호출하고 결과를 콘솔로 살펴보자.
1 2 3 4 5 6 |
addTodo() { this.heroService.addTodo(this.newTodo) .subscribe(body => { console.log(body); }); } |
보내는 데이터를 this.newTodo라는 객체를 보냈다. 그런데 여기서 newTodo 객체중 todo 변수에만 값을 할당하였는데, 객체로 데이터를 보내면 isFinished, created, updated, 이런 변수들도 전송이 되는가? undefined인 변수들은 내부에서 JSON.stringify()를 수행하면서 전송대상에서 제외된다.
뷰 바인딩
리턴된 데이터는 실제로 데이터베이스에 삽입된 데이터가 리턴된다. 이 데이터를 배열의 맨 앞쪽에 추가하자. 컴포넌트 개발방식에서는 이렇게 배열에 데이터만 추가하면된다. jquery에서처럼 모델 데이터를 얻은 다음 노드를 만들어서 다른 노드에 삽입할 필요가 없다. 단지, 모델 정보만 업데이트하면 이미 앞에서 뷰와 모델을 바인딩 시켜놨기 때문에 뷰가 자동으로 렌더링되서 보인다.
1 2 3 4 5 6 7 8 9 |
addTodo() { this.heroService.addTodo(this.newTodo) .subscribe(body => { console.log(body); this.todoList.unshift(body); // clear input this.newTodo.todo = null; }); } |
angular form validation
angular 에서는 두가지 form 방식이 있다. template=driven 방식과 reactive 방식. 여기서는 template-dirven방식으로 form validation방식을 살펴보겠다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<form #myForm="ngForm" (ngSubmit)="addTodo()"> <div class="row"> <div class="col-sm-8"> <div class="form-group"> <input type="text" class="form-control" placeholder="할일을 입력하세요." [(ngModel)]="newTodo.todo" name="todo" #todo="ngModel" required> <div [hidden]="!todo.touched || todo.valid" class="alert alert-danger"> todo is required </div> </div> </div> <div class="col-sm-4"> <button type="submit" class="btn btn-primary btn-block" [disabled]="!myForm.form.valid">추가</button> </div> </div> </form> |
#은 template reference variable이다. #myForm=”ngForm” 은 angular 컨텍스트에 myForm이라는 변수를 선언하는데 타입이 ngForm이라고 선언하는것과 동일하다.
먼저 input에서는 # 연산자를 컨트롤에 접근하여 각각의 validation을 체크한다. #todo=”ngModel” 로 선언하였기 때문에 angular context에서 todo 변수에 접근이 가능하다.
[hidden]=”todo.valid” 로 유효하지 않다면, 여기서는 requried 가 있으므로 입력된 값이 없으면 보여주게 된다.모든 input이 valid 한지 아닌지는 #myForm=”ngForm” 의 myForm.form.valid 로 전체 form validation 을 체크할 수 있다.
버튼이 disable 된걸 명시적으로 보여주기 위해서 아래와 같이 css를 추가한다.
1 2 3 4 5 6 7 8 |
button:disabled { background-color: #eee; color: #aaa; cursor: auto; &:hover { cursor: not-allowed; } } |