@RequestMapping("/")
- public String display(
- @ModelAttribute("form") Map<Integer, Map<String, Boolean>> form)
+ public String display(@ModelAttribute Form form)
{
- for (Integer id : form.keySet())
- for (String entry : form.get(id).keySet())
- LOG.info("{} - {}: {}", id, entry, form.get(id).get(entry));
+ for (Integer id : form.cards.keySet())
+ for (String entry : form.cards.get(id).keySet())
+ LOG.info("{} - {}: {}", id, entry, form.cards.get(id).get(entry));
return "form";
}
- @RequestMapping(path = "/", params = "row")
- public String addRow(
- @ModelAttribute("form") Map<Integer, Map<String, Boolean>> form,
- @RequestParam Integer row)
+ @RequestMapping(path = "/", params = "add=card")
+ public String addCard(@ModelAttribute Form form)
{
- LOG.info("Adding row #{}", row);
- form.put(row, new HashMap<>());
+ Integer next =
+ form.cards
+ .keySet()
+ .stream()
+ .reduce(0, (a, b) -> a > b ? a : b) + 1;
+
+ LOG.info("Adding new card #{}", next);
+ form.cards.put(next, new HashMap<>());
return "form";
}
- @RequestMapping(path = "/", params = "row")
- public String removeRow(
- @ModelAttribute("form") Map<Integer, Map<String, Boolean>> form,
- @RequestParam Integer row)
+ @RequestMapping(path = "/", params = "remove=card")
+ public String removeCard(
+ @ModelAttribute Form form,
+ @RequestParam Integer card)
{
- Map<String, Boolean> content = form.remove(row);
- LOG.info("Removed row #{} with content: {}", row, content);
+ Map<String, Boolean> content = form.cards.remove(card);
+ LOG.info("Removed card #{} with content: {}", card, content);
return "form";
}
- @RequestMapping(path = "/", params = { "row", "entry" })
- public String addEntry(
- @ModelAttribute("form") Map<Integer, Map<String, Boolean>> form,
- @RequestParam Integer row,
- @RequestParam String entry)
+ @RequestMapping(path = "/", params = "add=row")
+ public String addRow(@ModelAttribute Form form, @RequestParam Integer card)
{
- LOG.info("Adding entry {} to row #{}", entry, row);
- form.get(row).put(entry, Boolean.FALSE);
+ LOG.info("Adding row {} to card #{}", form.row.get(card), card);
+ form.cards.get(card).put(form.row.get(card), Boolean.FALSE);
return "form";
}
- @RequestMapping(path = "/", params = { "row", "entry" })
- public String removeEntry(
- @ModelAttribute("form") Map<Integer, Map<String, Boolean>> form,
- @RequestParam Integer row,
- @RequestParam String entry)
+ @RequestMapping(path = "/", params = "remove!=card")
+ public String removeRow(@ModelAttribute Form form, @RequestParam String remove)
{
- Boolean value = form.get(row).remove(entry);
- LOG.info("Removed entry {} with value {} from row #{}", entry, value, row);
+ String[] parts = remove.split(":", 2);
+ Integer card = Integer.valueOf(parts[0]);
+ String row = parts[1];
+ Boolean value = form.cards.get(card).remove(row);
+ LOG.info("Removed row {} with value {} from card #{}", row, value, card);
return "form";
}
}
--- /dev/null
+<!DOCTYPE html>
+<html lang="en" xmlns:th="http://www.thymeleaf.org">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+ <title>Demo: Multidimensional Map With Dynamic Binding</title>
+ <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
+ </head>
+ <body>
+ <nav class="navbar navbar-dark bg-primary navbar-expand navbar-dark flex-column">
+ <h2 class="navbar-brand">Demo: Multidimensional Map With Dynamic Binding</h2>
+ </nav>
+ <main class="container mt-5">
+ <form action="#" th:action="@{/}" th:object="${form}" method="get">
+ <div class="card" th:each="card : *{cards.rowSet()}">
+ <div class="card-header"><h1 th:text="|Card #${card.key}|">Card #X</h1></div>
+ <div class="card-body">
+ <div class="card-text">
+ <div class="form-group" th:each="row : ${card.value.rowSet()}">
+ <input type="checkbox" id="x" class="form-control" th:field="*{cards[__${card.key}__][__${row.key}__]}" />
+ <label for="x" th:for="${#ids.prev('cards[__${card.key}__][__${row.key}__]')}" th:text="${row.value}">ROW_NAME</label>
+ <button type="submit" name="removeRow" class="btn btn-primary" th:value="|${card.key}:${row.key}|">Remove</button>
+ </div>
+ <button type="submit" name="add" value="row" class="btn btn-primary">Add Row</button>
+ </div>
+ <div class="card-footer">
+ <button type="submit" name="remove" value="card" class="btn btn-primary">Remove Card</button>
+ </div>
+ </div>
+ </div>
+ <button type="submit" name="add" value="card" class="btn btn-primary">Add Card</button>
+ </form>
+ </main>
+ </body>
+</html>