article thumbnail image
Published 2022. 9. 8. 13:48

게시판에 사용할 폼 만들기

 

https://getbootstrap.com/docs/5.2/forms/form-control/

 

Form controls

Give textual form controls like <input>s and <textarea>s an upgrade with custom styles, sizing, focus states, and more.

getbootstrap.com

 

 

form 태그 안에 코드 추가

<div class="mb-3">
  <label for="exampleFormControlInput1" class="form-label">Email address</label>
  <input type="email" class="form-control" id="exampleFormControlInput1" placeholder="name@example.com">
</div>
<div class="mb-3">
  <label for="exampleFormControlTextarea1" class="form-label">Example textarea</label>
  <textarea class="form-control" id="exampleFormControlTextarea1" rows="3"></textarea>
</div>

 

 

form.html

<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments/common :: head('게시판')">
</head>

<body class="d-flex flex-column h-100">

<header th:replace="fragments/common :: menu('board')">
</header>

<!-- Begin page content -->
<main class="flex-shrink-0">
    <div class="container">
        <h2>게시판</h2>
        <div class="mb-3">
            <label for="title" class="form-label">제목</label>
            <input type="email" class="form-control" id="title" >
        </div>
        <form>
            <div class="mb-3">
                <label for="content" class="form-label">내용</label>
                <textarea class="form-control" id="content" rows="3"></textarea>
            </div>
        </form>
</main>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
</body>
</html>

 

 

 

취소, 확인 버튼 추가

 

 

form.html

<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments/common :: head('게시판')">
</head>

<body class="d-flex flex-column h-100">

<header th:replace="fragments/common :: menu('board')">
</header>

<!-- Begin page content -->
<main class="flex-shrink-0">
    <div class="container">
        <h2>게시판</h2>
        <div class="mb-3">
            <label for="title" class="form-label">제목</label>
            <input type="email" class="form-control" id="title" >
        </div>
        <form>
            <div class="mb-3">
                <label for="content" class="form-label">내용</label>
                <textarea class="form-control" id="content" rows="3"></textarea>
            </div>
            <div class="text-end">
                <a type="button" class="btn btn-primary" th:href="@{/board/list}">취소</a>
                <button type="submit" class="btn btn-primary">확인</button>
            </div>
        </form>
        </div>
</main>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
</body>
</html>

 

list.html

<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments/common :: head('게시판')">
</head>

<body class="d-flex flex-column h-100">

<header th:replace="fragments/common :: menu('board')">
</header>

<!-- Begin page content -->
<main class="flex-shrink-0">
    <div class="container">
        <h2>게시판</h2>
        <div>총 건수 : <span th:text="${#lists.size(boards)}"></span></div>
    </div>
    <table class="table">
        <thead>
        <tr>
            <th scope="col">번호</th>
            <th scope="col">제목</th>
            <th scope="col">작성자</th>
        </tr>
        </thead>
        <tbody>
        <tr th:each="board : ${boards}">
            <td th:text="${board.id}">Mark</td>
            <td th:text="${board.title}">Otto</td>
            <td>홍길동</td>
        </tr>
        </tbody>
    </table>
    <div class="text-end">
        <a type="button" class="btn btn-primary" th:href="@{/board/form}">쓰기</a>
    </div>
    </div>
</main>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
</body>
</html>

 

 

 

form 전송하기

 

https://spring.io/guides/gs/handling-form-submission/

 

Handling Form Submission

this guide is designed to get you productive as quickly as possible and using the latest Spring project releases and techniques as recommended by the Spring team

spring.io

 

 

package com.toy.board.web;

import com.toy.board.domain.Board;
import com.toy.board.reopsitory.BoardRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
@RequestMapping("/board")
public class BoardController {

    @Autowired
    private BoardRepository boardRepository;

    @GetMapping("/list")
    public String list(Model model) {
        List<Board> boards = boardRepository.findAll();
        model.addAttribute("boards", boards);
        return "/board/list";
    }

    @GetMapping("/form")
    public String form(Model model) {
        model.addAttribute("board", new Board());
        return "/board/form";
    }

    @PostMapping("/form")
    public String form(@ModelAttribute Board board) {
        boardRepository.save(board);
        return "redirect:/board/list";
    }
}

 

form.html

<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments/common :: head('게시판')">
</head>

<body class="d-flex flex-column h-100">

<header th:replace="fragments/common :: menu('board')">
</header>

<!-- Begin page content -->
<main class="flex-shrink-0">
    <div class="container">
        <h2>게시판</h2>
        <form action="#" th:action="@{/board/form}" th:object="${board}" method="post">
            <div class="mb-3">
                <label for="title" class="form-label">제목</label>
                <input type="text" class="form-control" id="title" th:field="*{title}">
            </div>
            <div class="mb-3">
                <label for="content" class="form-label">내용</label>
                <textarea class="form-control" id="content" rows="3" th:field="*{content}"></textarea>
            </div>
            <div class="text-end">
                <a type="button" class="btn btn-primary" th:href="@{/board/list}">취소</a>
                <button type="submit" class="btn btn-primary" >확인</button>
            </div>
        </form>
    </div>
</main>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
</body>
</html>

 

 

 

 

제목을 링크로 form 작성 페이지로 이동하기

 

https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html

 

Tutorial: Using Thymeleaf

1 Introducing Thymeleaf 1.1 What is Thymeleaf? Thymeleaf is a modern server-side Java template engine for both web and standalone environments, capable of processing HTML, XML, JavaScript, CSS and even plain text. The main goal of Thymeleaf is to provide a

www.thymeleaf.org

 

@GetMapping("/form")
public String form(Model model, @RequestParam(required = false) Long id) {

    if (id == null) {
        model.addAttribute("board", new Board());
    } else {
        Optional<Board> board = boardRepository.findById(id);
        model.addAttribute("board", board);
    }
    return "/board/form";
}

 

list.html

<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments/common :: head('게시판')">
</head>

<body class="d-flex flex-column h-100">

<header th:replace="fragments/common :: menu('board')">
</header>

<!-- Begin page content -->
<main class="flex-shrink-0">
    <div class="container">
        <h2>게시판</h2>
        <div>총 건수 : <span th:text="${#lists.size(boards)}"></span></div>
    </div>
    <table class="table">
        <thead>
        <tr>
            <th scope="col">번호</th>
            <th scope="col">제목</th>
            <th scope="col">작성자</th>
        </tr>
        </thead>
        <tbody>
        <tr th:each="board : ${boards}">
            <td th:text="${board.id}">Mark</td>
            <td><a th:text="${board.title}" th:href="@{/board/form(id=${board.id})}">Otto</a></td>
            <td>홍길동</td>
        </tr>
        </tbody>
    </table>
    <div class="text-end">
        <a type="button" class="btn btn-primary" th:href="@{/board/form}">쓰기</a>
    </div>
    </div>
</main>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
</body>
</html>

 

 

수정 기능 넣기

 

form.html

<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments/common :: head('게시판')">
</head>

<body class="d-flex flex-column h-100">

<header th:replace="fragments/common :: menu('board')">
</header>

<!-- Begin page content -->
<main class="flex-shrink-0">
    <div class="container">
        <h2>게시판</h2>
        <form action="#" th:action="@{/board/form}" th:object="${board}" method="post">
            <input type="hidden" th:field="*{id}">
            <div class="mb-3">
                <label for="title" class="form-label">제목</label>
                <input type="text" class="form-control" id="title" th:field="*{title}">
            </div>
            <div class="mb-3">
                <label for="content" class="form-label">내용</label>
                <textarea class="form-control" id="content" rows="3" th:field="*{content}"></textarea>
            </div>
            <div class="text-end">
                <a type="button" class="btn btn-primary" th:href="@{/board/list}">취소</a>
                <button type="submit" class="btn btn-primary" >확인</button>
            </div>
        </form>
    </div>
</main>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
</body>
</html>

 

form.html 파일에 코드 추가

<input type="hidden" th:field="*{id}">

 

 

form 데이터 검사하기

 

https://spring.io/guides/gs/validating-form-input/

 

Validating Form Input

this guide is designed to get you productive as quickly as possible and using the latest Spring project releases and techniques as recommended by the Spring team

spring.io

 

validation 의존성 추가

implementation 'org.springframework.boot:spring-boot-starter-validation'

 

board.java

package com.toy.board.domain;

import lombok.Data;


import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

@Entity
@Data
public class Board {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @Size(min=2, max=30)
    private String title;
    private String content;


}


@NotNull, @Size 어노테이션을 사용한다.

 

@PostMapping("/form")
public String form(@Valid Board board, BindingResult bindingResult) {

    if (bindingResult.hasErrors()) {
        return "board/form";
    }
    boardRepository.save(board);
    return "redirect:/board/list";
}

@ModelAttribute 대신 @Valid를 사용, BindingResult 를 통해 데이터를 검증한다.

 

 

에러 표시는 Bootstrap 을 이용한다.

 

https://getbootstrap.com/docs/5.2/forms/validation/#server-side

 

Validation

Provide valuable, actionable feedback to your users with HTML5 form validation, via browser default behaviors or custom styles and JavaScript.

getbootstrap.com

 

from.html

<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments/common :: head('게시판')">
</head>

<body class="d-flex flex-column h-100">

<header th:replace="fragments/common :: menu('board')">
</header>

<!-- Begin page content -->
<main class="flex-shrink-0">
    <div class="container">
        <h2>게시판</h2>
        <form action="#" th:action="@{/board/form}" th:object="${board}" method="post">
            <input type="hidden" th:field="*{id}">
            <div class="mb-3">
                <label for="title" class="form-label">제목</label>
                <input type="text" class="form-control" th:classappend="${#fields.hasErrors('title')} ? 'is-invalid'"
                       id="title" th:field="*{title}">
                <div class="invalid-feedback" th:if="${#fields.hasErrors('title')}" th:errors="*{title}">
                    제목 에러 메시지
                </div>
            </div>
            <div class="mb-3">
                <label for="content" class="form-label">내용</label>
                <textarea class="form-control" th:classappend="${#fields.hasErrors('content')} ? 'is-invalid'"
                          id="content" rows="3" th:field="*{content}"></textarea>
                <div class="invalid-feedback" th:if="${#fields.hasErrors('content')}" th:errors="*{content}">
                    내용 에러 메시지
                </div>
            </div>
            <div class="text-end">
                <a type="button" class="btn btn-primary" th:href="@{/board/list}">취소</a>
                <button type="submit" class="btn btn-primary" >확인</button>
            </div>
        </form>
    </div>
</main>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
</body>
</html>
th:classappend="${#fields.hasErrors('title')} ? 'is-invalid'"
 <div class="invalid-feedback" th:if="${#fields.hasErrors('title')}" th:errors="*{title}">
                    제목 에러 메시지
                </div>

위 코드들 추가

 

 

validator 커스텀 하기

 

BoardValidator.java

package com.toy.board.validator;

import com.toy.board.domain.Board;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;

@Component
public class BoardValidator implements Validator {

    @Override
    public boolean supports(Class<?> clazz) {
        return Board.class.equals(clazz);
    }

    @Override
    public void validate(Object obj, Errors errors) {
        Board b = (Board) obj;
        if (StringUtils.isEmpty(b.getContent())) {
            errors.rejectValue("content", "key", "내용을 입력하세요.");
        }
    }
}

erros.rejectValue : 첫 번째 파리미터 field 값, 두 번째 "error code", 세 번째 defaultMessage

 

Board.java

package com.toy.board.domain;

import lombok.Data;


import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

@Entity
@Data
public class Board {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @Size(min=2, max=30, message = "제목은 2자이상 30자 이하입니다.")
    private String title;
    private String content;


}


@Size 어노테이션 세 번째 파라미터에 message 값 넣기

 

 

'Bootstrap' 카테고리의 다른 글

Bootstrap - table, button  (0) 2022.09.07
Bootstrap - starter  (0) 2022.09.06
Bootstrap - Spring Boot에 적용하기  (0) 2022.09.02
복사했습니다!