사랑하애오
article thumbnail

이제 SBB가 점점 완성 되어가고 있다.
이번에는 더 많은 기능을 추가하기 전에 발견된 몇 가지 문제점을 해결하려고 한다.

발견된 문제점은 답글을 작성하거나 수정한 후에 항상 페이지 상단으로 스크롤이 이동되기 때문에
본인이 작성한 답변을 확인하려면 다시 스크롤을 내려서 확인해야 한다는 점이다.
이 문제는 답변을 추천한 경우에도 동일하게 발생한다.

Ajax와 같은 비동기 통신 기술을 사용하여 이 문제를 해결할 수도 있지만
여기서는 보다 쉬운 방법으로 이 문제를 해결해 보자.
HTML에는 URL 호출시 원하는 위치로 이동시켜 주는 앵커(anchor) 태그가 있다.
예를 들어 HTML 중간에 <a id="test"></a> 라는 앵커 태그가 있다면
이 HTML을 호출하는 URL 뒤에 #test 라고 붙여주면 해당 페이지가 호출되면서 해당 앵커로 스크롤이 이동된다.

답변등록, 답변수정, 답변추천 시 앵커 태그를 이용하여 원하는 위치로 이동할 수 있도록 수정해 보자.

1.  

2. 답변 앵커 추가

먼저 답변 작성, 수정시에 이동해야할 앵커 태그를 질문 상세 템플릿에 추가하자.

[파일명:/sbb/src/main/resources/templates/question_detail.html]

<code />
(... 생략 ...) <!-- 답변의 갯수 표시 --> <h5 class="border-bottom my-3 py-2" th:text="|${#lists.size(question.answerList)}개의 답변이 있습니다.|"></h5> <!-- 답변 반복 시작 --> <div class="card my-3" th:each="answer : ${question.answerList}"> <a th:id="|answer_${answer.id}|"></a> <div class="card-body"> (... 생략 ...)

답변이 반복되어 표시되는 th:each 바로 다음에 <a th:id="|answer_${answer.id}|"></a>와 같이 앵커 태그를 추가했다.
앵커 태그의 id 속성은 유일한 값이어야 하므로 answer_{{ answer.id }}와 같이 답변 id를 사용했다.

3.  

4. 답변 redirect

이제 답변을 등록하거나 수정할 때 위에서 지정한 앵커 태그로 이동하도록 코드를 수정하자. 다음은 답변 등록 또는 답변 수정을 한 뒤 사용했던 기존 코드의 일부이다.

<java />
return String.format("redirect:/question/detail/%s", answer.getQuestion().getId());

여기에 앵커를 포함하면 다음과 같다.

<code />
return String.format("redirect:/question/detail/%s#answer_%s", answer.getQuestion().getId(), answer.getId());

리다이렉트되는 질문 상세 URL에 #answer_2와 같은 앵커를 추가한 것이다.
이러한 방법으로 답변 작성, 수정, 추천의 리다이렉트 부분을 변경하자.

5.  

6. AnswerService

컨트롤러에서 답변이 등록된 위치로 이동하기 위해서는 답변 객체가 반드시 필요하다.
따라서 다음과 같이 AnswerService를 먼저 수정해야 한다.

[파일명: /sbb/src/main/java/com/mysite/sbb/answer/AnswerService.java]

<code />
(... 생략 ...) public class AnswerService { (... 생략 ...) public Answer create(Question question, String content, SiteUser author) { Answer answer = new Answer(); answer.setContent(content); answer.setCreateDate(LocalDateTime.now()); answer.setQuestion(question); answer.setAuthor(author); this.answerRepository.save(answer); return answer; } (... 생략 ...) }

7.  

8. AnswerController

그리고 컨트롤러의 리다이렉트 코드들을 다음과 같이 수정하자.

[파일명:/sbb/src/main/java/com/mysite/sbb/answer/AnswerController.java]

<code />
(... 생략 ...) public class AnswerController { (... 생략 ...) @PreAuthorize("isAuthenticated()") @PostMapping("/create/{id}") public String createAnswer(Model model, @PathVariable("id") Integer id, @Valid AnswerForm answerForm, BindingResult bindingResult, Principal principal) { Question question = this.questionService.getQuestion(id); SiteUser siteUser = this.userService.getUser(principal.getName()); if (bindingResult.hasErrors()) { model.addAttribute("question", question); return "question_detail"; } Answer answer = this.answerService.create(question, answerForm.getContent(), siteUser); return String.format("redirect:/question/detail/%s#answer_%s", answer.getQuestion().getId(), answer.getId()); } (... 생략 ...) @PreAuthorize("isAuthenticated()") @PostMapping("/modify/{id}") public String answerModify(@Valid AnswerForm answerForm, @PathVariable("id") Integer id, BindingResult bindingResult, Principal principal) { if (bindingResult.hasErrors()) { return "answer_form"; } Answer answer = this.answerService.getAnswer(id); if (!answer.getAuthor().getUsername().equals(principal.getName())) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "수정권한이 없습니다."); } this.answerService.modify(answer, answerForm.getContent()); return String.format("redirect:/question/detail/%s#answer_%s", answer.getQuestion().getId(), answer.getId()); } (... 생략 ...) @PreAuthorize("isAuthenticated()") @GetMapping("/vote/{id}") public String answerVote(Principal principal, @PathVariable("id") Integer id) { Answer answer = this.answerService.getAnswer(id); SiteUser siteUser = this.userService.getUser(principal.getName()); this.answerService.vote(answer, siteUser); return String.format("redirect:/question/detail/%s#answer_%s", answer.getQuestion().getId(), answer.getId()); } }

답변을 작성, 수정, 추천한 후에 해당 답변으로 이동하도록 앵커 태그를 추가해 주었다.

9.  

10. 답변 앵커 확인

이와 같이 수정한 후 답변을 등록할 때 스크롤이 지정한 앵커로 이동하는지 확인해 보자.

profile

사랑하애오

@사랑하애

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!