Challenge – Part 3
Goal: Implement the update functionality.
Task 1
Every update button inside the table must make a GET request to the homepage.
th:href="@{/}"
Task 2
Every item that gets submitted should carry an id
.
public class Item {
//...
private String id;
public Item() {
this.id = UUID.randomUUID().toString();
}
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
//...
}
Upon pressing update, the GET request needs to include an id
parameter that identifies the selected item.
th:href="@{/(param = ${element.field})}"
Submit another item to the inventory table. Then, press update.
Output: the parameter should get carried over
Print the id
inside the handler method, and repeat the process.
public String getForm(Model model, @RequestParam(required = false) String id) {
//...
System.out.println("id: " + id);
//...
return "form";
}
Terminal Output: id: 5500b7d3-73ac-4d1d-9596-1b5bbca3cae1
Task 3
Before returning the form
view, check if the id
matches any of the items inside the data store.
public String getForm(Model model, @RequestParam(required = false) String id) {
// if there is a match
if (match) {
model.addAttribute("item", matching object);
}
else { // if there is no match
model.addAttribute("item", new Item());
}
//etc...
}
In there is a match, your form elements will pre-populate with values from the model attribute.
Task 4
- Upon form submission, make sure the id is part of the POST request payload.
<input type="hidden" th:field="*{YOUR_ID_FIELD}">
-
(Optional): Inside
handleSubmit()
, confirm that the item'sid
is being received. -
Use the
id
to check if the submitted item already exists- If so, your handler method must update the datastore.
- Otherwise, your handler method must add to the datastore.
-
Redirect the client to the
inventory
view. -
Test both scenarios before moving to the next task.
Task 5
FlashAttribute
: Data that survives a redirect.
Inside Constants.java
, create another constant called SUCCESS_STATUS
.
public static final String SUCCESS_STATUS = "success";
Inside handleSubmit()
, add the following parameter:
(Item item, RedirectAttributes redirectAttributes)
Before redirection, add a FlashAttribute
with key: status
and value: Constants.SUCCESS_STATUS
.
redirectAttributes.addFlashAttribute("status", Constants.SUCCESS_STATUS);
After redirecting the client to /inventory
, the FlashAttribute
will populate Model model
.
@GetMapping("/inventory")
public String getInventory(Model model)
Task 6
Display the following div
only if status
equals success
.
<div class="alert success"> <strong> You successfully submited the item! </strong> </div>
Task 7
Your next task is to forbid updates if the new orderDate
has a 5-day discrepancy from the previous one.
Inside Constants.java
, create another constant called FAILED_STATUS
.
public static final String FAILED_STATUS = "failed";
The following method returns true
if two dates are within 5 days.
public boolean within5Days(Date newDate, Date oldDate) {
long diff = Math.abs(newDate.getTime() - oldDate.getTime());
return (int) (TimeUnit.MILLISECONDS.toDays(diff)) <= 5;
}
The next step is to update handleSubmit()
@PostMapping("/submitItem")
public String handleSubmit(Item item, RedirectAttributes redirectAttributes) {
}
- The
status
variable starts off equalingsuccess
.
@PostMapping("/submitItem")
public String handleSubmit(Item item, RedirectAttributes redirectAttributes) {
int index = getIndexFromId(item.getId());
/****************** 1 ******************/
String status = Constants.SUCCESS_STATUS;
- If the
id
doesn't have a match, the submitted item gets added to the datastore.
@PostMapping("/submitItem")
public String handleSubmit(Item item, RedirectAttributes redirectAttributes) {
int index = getIndexFromId(item.getId());
/****************** 1 ******************/
String status = Constants.SUCCESS_STATUS;
/****************** 2 ******************/
if (index == Constants.NOT_FOUND) {
items.add(item);
}
- If there is a match, and the updated date is within 5 days, the datastore gets updated.
@PostMapping("/submitItem")
public String handleSubmit(Item item, RedirectAttributes redirectAttributes) {
int index = getIndexFromId(item.getId());
/****************** 1 ******************/
String status = Constants.SUCCESS_STATUS;
/****************** 2 ******************/
if (index == Constants.NOT_FOUND) {
items.add(item);
}
/****************** 3 ******************/
else if (within5Days(item.getDate(), items.get(index).getDate())){
items.set(index, item);
}
- If there is a match, but the updated date is not within 5 days, nothing happens and the
status
variable equalsfailed
.
@PostMapping("/submitItem")
public String handleSubmit(Item item, RedirectAttributes redirectAttributes) {
int index = getIndexFromId(item.getId());
/****************** 1 ******************/
String status = Constants.SUCCESS_STATUS;
/****************** 2 ******************/
if (index == Constants.NOT_FOUND) {
items.add(item);
}
/****************** 3 ******************/
else if (within5Days(item.getDate(), items.get(index).getDate())){
items.set(index, item);
}
/****************** 4 ******************/
else {
status = Constants.FAILED_STATUS;
}
redirectAttributes.addFlashAttribute("status", status);
return "redirect:/inventory";
}
HTML
Add a Thymeleaf attribute that displays the div
only if the status
attribute equals failed
.
<div class="alert"> <strong > You failed to submit the item. </strong> </div>
Finally, try updating an item's date beyond the 5-day threshold.