스프링과 JPA 기반 웹 애플리케이션 개발 #28 프로필 수정 폼
스프링과 JPA 기반 웹 애플리케이션 개발 #28 프로필 수정 폼
해당 내용은 인프런, 스프링과 JPA 기반 웹 애플리케이션 개발의 강의 내용을 바탕으로 작성된 내용입니다.
강의를 학습하며 요약한 내용을 출처를 표기하고 블로깅 또는 문서로 공개하는 것을 허용합니다 라는 원칙 하에 요약 내용을 공개합니다. 출처는 위에 언급되어있듯, 인프런, 스프링과 JPA 기반 웹 애플리케이션 개발입니다.
제가 학습한 소스코드는 https://github.com/n00nietzsche/jakestudy_webapp 에 지속적으로 업로드 됩니다. 매 커밋 메세지에 강의의 어디 부분까지 진행됐는지 기록해놓겠습니다.
프로필 수정
- 컨트롤러
Bio
,Link
,Occupation
,Location
정보만 입력받아서Account
정보를 수정한다.
Profile 클래스 생성
@Data
public class Profile {
private String bio;
private String url;
private String occupation;
private String location;
public Profile(Account account) {
this.bio = account.getBio();
this.url = account.getUrl();
this.occupation = account.getOccupation();
this.location = account.getLocation();
}
}
Profile
클래스는 Account
에서 Profile
에 관련된 부분만 빼서 멤버로 만든 클래스이다.
SettingsController 클래스 생성
@Controller
@RequiredArgsConstructor
public class SettingsController {
private final AccountRepository accountRepository;
@GetMapping("/settings/profile")
// 리턴 타입을 void 로 바꿔도,
// `@GetMapping`의 value() 엘리먼트를 이용하여
// 뷰 네임을 추측해서 자동으로 `/settings/profile`로 가긴 한다.
public String profileUpdateForm(@CurrentUserAccount UserAccount userAccount, Model model) {
Account currentAccount = accountRepository.findById(userAccount.getId()).get();
model.addAttribute(currentAccount);
model.addAttribute(new Profile(currentAccount));
return "settings/profile";
}
}
SettingsController
는 설정과 관련된 페이지에 대한 컨트롤러이다. profileUpdateForm
메소드는 Account
정보 중 이전에 생성했던 Profile
과 관련된 부분만 모델로 내려주면서 settings/profile
뷰를 반환하는 메소드이다.
사실 스프링에서
@GetMapping
이 적용된 메소드의 리턴 타입을void
로 해도,@GetMapping
애노테이션의value()
엘리먼트를 보고 자동으로 뷰의 경로를 추측하는 기능이 있어서/settings/profile
을 자동으로 찾아주지만, 명시적으로 작성하기 위해 뷰의 이름을 직접 반환해주었다.
Fragments.html 추가 작성
settings-menu (currentMenu)
<!-- (currentMenu) 라는 곳으로 인자를 받아서 어떤 것을 active 할 지 선택할 수 있다. -->
<div th:fragment="settings-menu (currentMenu)" class="list-group">
<a class="list-group-item list-group-item-action"
th:classappend="${currentMenu == 'profile'}? active"
href="#" th:href="@{/settings/profile}">프로필</a>
<a class="list-group-item list-group-item-action"
th:classappend="${currentMenu == 'password'}? active"
href="#" th:href="@{/settings/password}">패스워드</a>
<a class="list-group-item list-group-item-action"
th:classappend="${currentMenu == 'notifications'}? active"
href="#" th:href="@{/settings/notifications}">알림 설정</a>
<a class="list-group-item list-group-item-action"
th:classappend="${currentMenu == 'tags'}? active"
href="#" th:href="@{/settings/tags}">관심 주제</a>
<a class="list-group-item list-group-item-action"
th:classappend="${currentMenu == 'zones'}? active"
href="#" th:href="@{/settings/zones}">활동 지역</a>
<a class="list-group-item list-group-item-action list-group-item-danger"
th:classappend="${currentMenu == 'account'}? active"
href="#" th:href="@{/settings/account}">계정</a>
</div>
위는 처음 사용하는 패턴의 fragment
인데, th:fragment
의 속성 값에 마지막에 (currentMenu)
라는 문자열을 추가하여 argument 처럼 이용한 형태이다.
th:classappend
속성을 이용하여 해당 argument를 활용할 수 있다. class에 active
라는 문자를 append하면 활성화된 메뉴로 보인다.
profile.html 작성
<!DOCTYPE html>
<html lang="en"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<title>회원가입</title>
<th:block th:replace="fragments :: headLibraryInjection"></th:block>
</head>
<body class="bg-light">
<th:block th:replace="fragments :: main-nav"></th:block>
<div class="alert alert-warning" role="alert" th:if="${account != null && !account?.emailVerified}">
스터디올래 가입을 완료하려면 <a href="#" th:href="@{/check-email}" class="alert-link">계정 인증 이메일을 확인</a>하세요
</div>
<div class="container">
<!-- row의 기본은 col-12만큼의 크기를 갖는다.-->
<div class="row mt-5 justify-content-center">
<div class="col-2">
<div th:replace="fragments :: settings-menu(currentMenu='profile')"></div>
</div>
<div class="col-8">
<div class="row">
<h2 class="col-sm-12" th:text="${account.nickname}">현재 사용자 닉네임</h2>
</div>
<div class="row mt-3">
<form class="col-sm-6" action="#" th:action="@{/settings/profile}"
th:object="${profile}" method="post" novalidate>
<div class="form-group">
<label for="bio">한 줄 소개</label>
<input id="bio" type="text" th:field="*{bio}" class="form-control"
placeholder="간략한 소개를 부탁합니다." aria-describedby="bioHelp" required>
<small id="bioHelp" class="form-text text-muted">
길지 않게 35자 이내로 입력하세요.
</small>
<small class="form-text text-danger" th:if="${#fields.hasErrors('bio')}" th:errors="*{bio}">
조금 길어요
</small>
</div>
<div class="form-group">
<label for="url">링크</label>
<input id="url" type="text" th:field="*{url}" class="form-control"
placeholder="https://jake_study.com" aria-describedby="urlHelp" required>
<small id="urlHelp" class="form-text text-muted">
길지 않게 35자 이내로 입력하세요.
</small>
<small class="form-text text-danger" th:if="${#fields.hasErrors('url')}" th:errors="*{url}">
올바른 URL이 아닙니다. 예시처럼 입력해주세요.
</small>
</div>
<div class="form-group">
<label for="occupation">직업</label>
<input id="occupation" type="text" th:field="*{occupation}" class="form-control"
placeholder="어떤 일을 하고계신가요?" aria-describedby="occupationHelp" required>
<small id="occupationHelp" class="form-text text-muted">
개발자? 매니저? 취준생? 대표님?
</small>
</div>
<div class="form-group">
<label for="location">활동 지역</label>
<input id="location" type="text" th:field="*{location}" class="form-control"
placeholder="Redmond, WA, USA" aria-describedby="locationHelp" required>
<small id="locationHelp" class="form-text text-muted">
주요 활동(사는 곳이나 직장을 다니는 곳 또는 놀러 다니는 곳) 지역의 도시 이름을 알려주세요.
</small>
</div>
<div class="form-group">
<button class="btn btn-primary btn-block" type="submit"
aria-describedby="submitHelp">수정하기</button>
</div>
</form>
</div>
</div>
</div>
<th:block th:replace="fragments :: footer"></th:block>
</div>
<script th:replace="fragments :: form-validation"></script>
</body>
</html>
Author And Source
이 문제에 관하여(스프링과 JPA 기반 웹 애플리케이션 개발 #28 프로필 수정 폼), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jakeseo_me/스프링과-JPA-기반-웹-애플리케이션-개발-28-프로필-수정-폼저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)