화면구성
컴포넌트를 생성한다.
1 |
ng g component admin/correct-hero |
라우팅을 추가한다.
1 |
{path: 'correct/:hero_id', component: CorrectHeroComponent} |
수정 버튼에 라우트링크를 추가한다.
1 |
<button class="btn btn-info btn-sm" routerLink="/admin/correct/{{hero.hero_id}}">수정</button> |
수정은 신규로 등록하는거 보다 더 어렵다. 먼저 등록된 정보를 가져와서 바인딩을 해야 하기 때문이다.
먼저, 기존 register-hero.component.html 화면을 그대로 가져오자.
그리고, component도 기존 register-hero.component.ts 생성자 부분을 그대로 가져오고 hero-detail에서 사용한 hero_id로 hero를 가져와서 바인딩한다.
ReactiveForm에서 setValue와 patchValue 두개의 차이점을 명확히 알아야 한다.
먼저 setValue로 했을때 왜 안되고, patchValue는 왜 되고 차이점이 무엇인지 확인해보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
export class CorrectHeroComponent implements OnInit { form: FormGroup; powers = ['flying', 'penetration', 'hacking', 'strength']; constructor(private fb: FormBuilder, private adminService: AdminService, private toaster: ToasterService, private route: ActivatedRoute, private heroService: HeroService) { this.form = this.fb.group({ name: [null, Validators.compose([Validators.required, Validators.minLength(5), Validators.maxLength(20)])], email: [null, Validators.compose([Validators.required, Validators.email])], sex: [null, Validators.required], country: [null, Validators.required], address: null, power: this.fb.array(this.powers.map(x => !1)), photo: null }); } ngOnInit() { this.route.params .subscribe(params => { console.log(params); this.getHero(+params['hero_id']); }); } getHero(id: number) { this.heroService.getHero(id) .subscribe(hero => { // hero에 있는 hero_id가 매핑이 안된다. // this.form.setValue(hero); this.form.patchValue(hero); }); } } |
power 부분만 바인딩이 안되고 대부분이 바인딩 된 걸 확인할 수 있다.
power는 스트링타입으로 DB에 저장되어있고, 예를들어 ‘flying,strength’ 로 되어있다면 이것을 [‘flying, ‘strength’] 로 변환한 다음 다시 [true, false, false, true]로 변환해야 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
getHero(id: number) { this.heroService.getHero(id) .subscribe(hero => { // power에 A, B 를 [A, B]로 변환후 [true, false, true, false] 로 변환해야 한다. let powerlist = hero.power.split(','); let result = this.powers.map(item => (powerlist.indexOf(item) > -1) ? true : false); // hero에 있는 hero_id가 매핑이 안된다. // this.form.setValue(hero); delete hero.power; this.form.patchValue(hero); this.form.patchValue({power: result}); }); } |
수정 로직
서비스에 수정 api를 추가한다.
1 2 3 |
modifyHero(hero: Hero): Observable<ResultVo> { return this.http.post<ResultVo>(`${environment.HOST}/api/hero`, hero, {headers: this.headers}); } |
등록시 사용했던 register 함수를 modify 함수로 리팩토링 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
modify() { console.log('modify'); if (!this.form.valid) { // to validate all form fields Object.keys(this.form.controls).forEach(key => { const control = this.form.controls[key]; control.markAsTouched({onlySelf: true}); }); return; } const power = this.form.controls['power'].value .map((item, index) => item ? this.powers[index] : false) .filter(item => item ? true : false); console.log(power); const sendForm = Object.assign({}, this.form.value); // DB에는 스트링 배열 타입이 아니라 콤마로 분리된 스트링으로 넣어야 한다. sendForm.power = power.toString(); console.log(sendForm); this.adminService.modifyHero(sendForm) .subscribe(body => { console.log(body); this.toaster.pop('success', 'success', '수정되었습니다!'); // form 초기화 // this.form.reset({}); }); } |