728x90
반응형
SMALL
만약 답변이 여러 개인 상태에서 수정하거나 삭제하면 리다이렉트로 화면이 재실행되기 때문에
무조건 페이지 상단으로 이동하게 된다. 그래서 자신이 작성한 답변을 확인하려면 스크롤을 다시 내려야 하는 경우가 있다.

비동기 방식을 이용할 수도 있지만, HTML에는 URL을 호출할 때 원하는 위치로 이동해주는 앵커(anchor)태그가 있다. 즉, <a>태그를 활용하여 답변 등록, 수정, 추천 시 원하는 위치로 이동할 수 있다.

 

답변 앵커 추가하기

/templates/question_detail.html

...
<!-- 답변 반복 시작 -->
<div class="card my-3" th:each="answer : ${question.answerList}">
	<a th:id="|answer_${answer.id}|"></a>
	<div class="card-body">
...

위처럼 <a>태그를 추가하자. 여기서 id 속성은 유일한 값이어야 하므로 답변의 id값을 사용했다.

 

리다이렉트 수정하기

이제 답변 등록, 수정 시 위에서 지정한 a태그로 이동하게끔 코드를 수정해야한다.

먼저 원래 컨트롤러에서 답변 등록, 수정 후 리다이렉트하는 코드를 보면

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

위와 같다. 이러한 코드들을

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

이렇게 앵커를 추가해야한다. 이 때 수정해야 하는 곳은 총 3곳으로 답변 등록, 수정, 추천 부분이다.

추후 컨트롤러 수정 단계에서 수정해보자.

 

답변 서비스 수정하기

답변 컨트롤러에서 답변이 등록된 위치로 이동하려면 답변의 객체가 필요하다.

/answer/AnswerService.java

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;
	}

메서드의 리턴타입을 Answer로 수정하고 answer을 리턴하도록 했다.

 

답변 컨트롤러 수정하기

/answer/AnswerController.java

@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, BindingResult bindingResult,
			@PathVariable("id") Integer id, 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 questionVote(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());
	}

answerService.create메서드를 위에서 리턴타입이 Answer로 수정했기 때문에 answer객체로 받아주고

앞서 말했듯이 return 값의 URL을 수정해준다.

 

그리고 답변 수정하는 부분과 답변 추천 기능의 return값을 수정해준다.

 

결과 확인하기

댓글을 미리 여러개 작성해놓았다. 마지막 댓글을 수저해보자.
댓글을 수정하고 저장해보자.
리다이렉트가 되어도 상단이 아닌 해당 답변위치로 이동했다. 위의 url을 보면 #answer_14를 볼 수 있다.

728x90
반응형
LIST

+ Recent posts