-Continued from Last time --Create a simple CRUD app with Spring Boot --This time, validate the input area --Make name and age required --Age should be in the range 0-150 --Team name can be up to 20 characters
--Validation setting annotates variables of entity class
--Edit Player.java
src/main/java/com/example/baseball/domain/Player.java
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @NotEmpty // ①
    private String name;
    @NotNull // ②
    @Min(value = 0) // ③
    @Max(value = 150)
    private Integer age;
    @Size(max = 20) // ④
    private String team;
    private String position;
-①: If @NotEmpty is added, null and empty string will not be allowed.
-②: If @NotNull is added, null will not be allowed.
--③: Set the minimum value with @ Min and the maximum value with @ Max
-④: Add @Size to limit the number of characters
--Add a process to return to the original screen if there is an error
--Modify PlayerController.java
src/main/java/com/example/baseball/controller/PlayerController.java
    @GetMapping("new")
    public String newPlayer(Model model) {
        // ①
        Player player = new Player();
        model.addAttribute("player", player);
        return "players/new";
    }
    @PostMapping
    public String create(@Valid @ModelAttribute Player player, BindingResult bindingResult) { // ②
        if(bindingResult.hasErrors()) return "players/new"; // ③
        playerService.save(player);
        return "redirect:/players";
    }
    @PutMapping("{id}")
    public String update(@PathVariable Long id, @Valid @ModelAttribute Player player, BindingResult bindingResult) {
        if(bindingResult.hasErrors()) return "players/edit";
        player.setId(id);
        playerService.save(player);
        return "redirect:/players";
    }
-①: Pass the Player instance to the new creation screen
--Without this, the contents entered at the time of the input error cannot be retained.
-②: By adding @Valid to player, it becomes a validation check target.
--Annotations are arranged side by side, but @Valid depends on player
@Valid @ModelAttribute Player player
//↑ and ↓ are the same
@Valid
@ModelAttribute
Player player
-②: If there is an error, the error information is set in BindingResult bindingResult.
--③: If there is an error, bindingResult.hasErrors () returns true, so in that case it is returned to the original screen.
new.html
--Display an error message when there is an error and it is thrown back to the controller
src/main/resources/templates/players/new.html
      <!-- ① -->
      <form th:action="@{/players}" th:method="post" th:object="${player}">
        <!-- ② -->
        <div class="form-group" th:classappend="${#fields.hasErrors('name')}? has-error">
          <label class="control-label">name</label>
          <input class="form-control" type="text" th:field="*{name}" />
          <!-- ③ -->
          <span class="text-danger" th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></span>
        </div>
        <div class="form-group" th:classappend="${#fields.hasErrors('age')}? has-error">
          <label class="control-label">age</label>
          <input class="form-control" type="number" th:field="*{age}" />
          <span class="text-danger" th:if="${#fields.hasErrors('age')}" th:errors="*{age}"></span>
        </div>
        <div class="form-group" th:classappend="${#fields.hasErrors('team')}? has-error">
          <label class="control-label">Team name</label>
          <input class="form-control" type="text" th:field="*{team}" />
          <span class="text-danger" th:if="${#fields.hasErrors('team')}" th:errors="*{team}"></span>
        </div>
        <div class="form-group" th:classappend="${#fields.hasErrors('position')}? has-error">
          <label class="control-label">Defensive position</label>
          <input class="form-control" type="text" th:field="*{position}" />
          <span class="text-danger" th:if="${#fields.hasErrors('position')}" th:errors="*{position}"></span>
        </div>
        <button class="btn btn-default" type="submit">Create</button>
      </form>
--①: Since the player is now received from the controller, set it to th: object.
--Modified so that each input field also uses th: field (see ③ of here)
――The reason why I made this change is because I want to reset the input contents to value when an error occurs and it is thrown back.
--②: th: classappend =" $ {# fields.hasErrors ('name')}? has-error " means has in the class attribute when # fields.hasErrors ('name') is true. -Add error
--Error information is contained in # fields
--If you add has-error to the class attribute, the label and frame will turn red according to the Bootstrap definition.
--③: Area for displaying error messages
--Elements with th: if set are displayed only when the value of th: if is true (in this case, when there is an error).
-- th: errors =" * {name} " displays all error messages set for * {name}
--Although it does not occur in this example, if there are multiple errors, all will be displayed with line breaks.
edit.html
--Added the same processing as new.html
src/main/resources/templates/players/edit.html
      <form th:action="@{/players/{id}(id=*{id})}" th:method="put" th:object="${player}">
        <div class="form-group" th:classappend="${#fields.hasErrors('name')}? has-error">
          <label class="control-label">name</label>
          <input class="form-control" type="text" th:field="*{name}" />
          <span class="text-danger" th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></span>
        </div>
        <div class="form-group" th:classappend="${#fields.hasErrors('age')}? has-error">
          <label class="control-label">age</label>
          <input class="form-control" type="number" th:field="*{age}" />
          <span class="text-danger" th:if="${#fields.hasErrors('age')}" th:errors="*{age}"></span>
        </div>
        <div class="form-group" th:classappend="${#fields.hasErrors('team')}? has-error">
          <label class="control-label">Team name</label>
          <input class="form-control" type="text" th:field="*{team}" />
          <span class="text-danger" th:if="${#fields.hasErrors('team')}" th:errors="*{team}"></span>
        </div>
        <div class="form-group" th:classappend="${#fields.hasErrors('position')}? has-error">
          <label class="control-label">Defensive position</label>
          <input class="form-control" type="text" th:field="*{position}" />
          <span class="text-danger" th:if="${#fields.hasErrors('position')}" th:errors="*{position}"></span>
        </div>
        <button class="btn btn-default" type="submit">update</button>
      </form>
--With the modifications made so far, when you access http: // localhost: 8080 / players, the behavior is as follows.

--Next is here
Recommended Posts