CustomMenu

Wednesday, February 19, 2014

Spring MVC 4 - Thymeleaf CRUD - Part 3

This is the third part of a series on moving our simple Spring MVC 4 CRUD application from JSP to Thymeleaf.  The first part of the series can be found at Spring MVC 4 - Thymeleaf CRUD - Part 1.  In part one, simple list functionality was built.  In part two we created the "add" functionality on the same page.  In this post we will create the update/edit functionality and link to it from the list page.

1. The first step is to modify the StrategyController HTTP-GET method for updating a strategy.  The old and new versions of the relevant HTTP-GET method are below.  The only difference is that the new method is passing the StrategyDTO object rather than the Strategy object to Thymeleaf.
    
@RequestMapping(value="/edit/{id}", method=RequestMethod.GET)
public ModelAndView editStrategyPage(@PathVariable Integer id) {
        ModelAndView modelAndView = new ModelAndView("strategy-edit");
        Strategy strategy = strategyService.getStrategy(id);
        modelAndView.addObject("strategy",strategy);
        return modelAndView;
    }
@RequestMapping(value="/edit", method=RequestMethod.GET)
public ModelAndView editStrategyPage(@RequestParam(value="id", required=true) Integer id) {
    ModelAndView modelAndView = new ModelAndView("strategy-edit");
    Strategy strategy = strategyService.getStrategy(id);
    StrategyDTO strategyDTO = StrategyMapper.getDTO(strategy);
    modelAndView.addObject("strategyDTO",strategyDTO);
    return modelAndView;
}

2. The second step is to modify the StrategyController HTTP-POST method for updating a strategy.  The old and new versions of the relevant HTTP-POST method are shown below.

As with the HTTP-GET method, the new method is using the StrategyDTO object rather than the Strategy object received from Thymeleaf.  In addition, this new method is receiving a parameter named "action" that indicates whether to "save" or "cancel" the update.  After the new method is finished, it will redirect the user to the list page.
    @RequestMapping(value="/edit/{id}", method=RequestMethod.POST)
    public ModelAndView edditingStrategy(@ModelAttribute Strategy strategy, @PathVariable Integer id) {
        ModelAndView modelAndView = new ModelAndView("home");
        strategyService.updateStrategy(strategy);
        String message = "Strategy was successfully edited.";
        modelAndView.addObject("message", message);
        return modelAndView;
    }
@RequestMapping(value="/edit", method=RequestMethod.POST)
public ModelAndView editingStrategy(@ModelAttribute StrategyDTO strategyDTO, 
        @RequestParam(value="action", required=true) String action) {

    ModelAndView modelAndView = new ModelAndView("redirect:/strategy/list");
    String message = null;

    if (action.equals("save")) {
        Strategy strategy = StrategyMapper.getStrategy(strategyDTO);
        strategyService.updateStrategy(strategy);
        message = "Strategy " + strategy.getId() + " was successfully edited";
        modelAndView.addObject("message", message);         
    }

    if (action.equals("cancel")) {
        message = "Strategy " + strategyDTO.getId() + " edit cancelled";
    }

    return modelAndView;
}

3. The next step is to create the html page for editing a strategy.  We will call this page strategy-edit.html, and the full file is shown below.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
 xmlns:th="http://www.thymeleaf.org">
<head data-th-fragment="header">
    <meta charset="utf-8" />
 <link type="text/css" rel="stylesheet" href="../../resources/css/style.css" th:href="@{/resources/css/style.css}"/>
 <title data-th-text="#{strategy.edit.page.title}">temp title</title>
</head>
<body>
<h1 data-th-text="#{strategy.edit.head.title}">temp heading</h1>
 <form action="#" data-th-action="@{/strategy/edit}" data-th-object="${strategyDTO}" method="post">
 <table class="box-table-a">
  <caption data-th-text="#{strategy.edit.form.title}">Add Title</caption>
  <tbody>
   <tr>
    <td data-th-text="#{strategy.list.type.label}">Temp Type</td>
    <td><input type="text" hidden="hidden" data-th-value="*{id}" data-th-field="*{id}" />
        <input type="text" data-th-value="*{type}" data-th-field="*{type}" /></td>
   </tr>
   <tr>
    <td data-th-text="#{strategy.list.name.label}">Temp Name</td>
    <td><input type="text" data-th-value="*{name}" data-th-field="*{name}" /></td>
   </tr>
   <tr>
    <td>
     <button type="submit" name="action" value="save" data-th-text="#{update.button.label}">save</button>
    </td>
    <td>
     <button type="submit" name="action" value="cancel" data-th-text="#{cancel.button.label}">cancel</button>
    </td>
   </tr>
  </tbody>
 </table>
 </form>
</body>
</html>
There are a few things to note on this page, but for the most part it is similar to the list page.  The form is associated with a POST action that will post the strategyDTO object back to the HTTP-POST edit method on the controller.

The strategyDTO object is received by the form with it's variables already populated by the HTTP-GET edit method call on the controller.  The values of these variables populate the corresponding data-th-value attributes in the form (e.g. *{name}).  These values pre-populate the fields in the form.  These form fields can then be changed (or not) by the user, with the values stored in the data-th-field attributes of the form.  When a button is selected, the data in the field attributes are stored in the strategyDTO object and the object is posted back to the controller for processing in the HTTP-POST edit method.

4. The last step before demoing the application is to modify the list page to correctly link to the edit page we just created.  The relevant section of code in the strategy-list.html file is shown below.  The only change that was made to this code was to add the data-th-href entry.  This code will build a link for each strategy in the list, with the link containing the id of a given strategy.
<tr data-th-each="strategy : ${strategies}">
    <td data-th-text="${strategy.id}">1</td>
    <td data-th-text="${strategy.type}">Iron Butterfly</td>
    <td data-th-text="${strategy.name}">Triple Butter</td>
    <td><a href="#" >delete</a> | 
        <a href="#" data-th-href="@{/strategy/edit(id=${strategy.id})}">edit</a>
    </td>
</tr>

5. We can now run the application, navigate to the list page, and select edit on a strategy.  The screenshot below is the edit page for the second strategy.

We then edit the strategy name.

And finally we select the update button and are returned to the list screen.  Our update should now be visible in the list.

If we had instead selected the cancel button, we would have been redirected to the list page with no updates having occurred.

In Part 4, we will create the delete functionality so that we can delete the strategies in the database.  There are links on the list page for this functionality, but these links are currently stubs.

Code at GitHub: https://github.com/dtr-trading/spring-ex04

No comments:

Post a Comment