Lab12 order navigation
Goal¶
Now that you've displayed all the orders, let's add links so you can view the details of each order.
Make Thymeleaf Reloading Easier
To make it easier to see changes without explicitly restarting the application, make sure you have the following two properties in the application.properties
file:
spring.thymeleaf.mode: HTML
spring.thymeleaf.cache: false
If you don't have that file, create it in the /resources
directory.
Once you have that set up, anytime you rebuild the project by doing CMD + F9, Spring and Thymeleaf will reload any changed files.
A. Create a Root (Home) Page¶
-
Copy the following into a Test class called WebIntegrationTest and make sure it's in the src/test folder.
package com.welltestedlearning.cvm; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import static org.hamcrest.Matchers.containsString; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc public class WebIntegrationTest { @Autowired private MockMvc mockMvc; @Test public void homePageExists() throws Exception { mockMvc.perform(get("/index.html")) .andExpect(status().isOk()) .andExpect(content().string(containsString("<title>Coffee</title>"))); } }
-
Run it and it should fail.
-
Create a new HTML page named
index.html
and place it in the/src/main/resources/static
directory:<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Coffee</title> </head> <body> <h1>Welcome to the Coffee Vending Machine.</h1> <br/> <div><a href="/coffee-order">View all coffee orders</a></div> </body> </html>
-
Run the
WebIntegrationTest
from above and it should pass. -
Also verify it by going to
http://localhost:8080/
and trying out the link.
B. Link to Order View¶
In this section, you'll use the th:href
tag to create links to view a specific order page.
Thymeleaf URL Syntax Reference
You can find the docs for the Thymeleaf URL (href) Syntax here: http://www.thymeleaf.org/doc/articles/standardurlsyntax.html
Background¶
You'll update the all-coffee-orders.html
template to add a link (aka "anchor" or "href") surrounding the order's name that will link to the details page for that order.
With normal static HTML, a link looks like this:
<a href="/coffee-order/1">Megan</a>
for Megan's order.We want to generate a link that will point to
/coffee-order/1
for an order with an ID of 1, and link to/coffee-order/5
for an order with an ID of 5.
Parameterize Example¶
Thymeleaf URL Syntax Reference
Thymeleaf docs for variable replacement is here: http://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#using-and-displaying-variables
As an example, to produce a link to a product page using its Product SKU (similar to an ID), we would use the @{}
expression, with an embedded ${}
variable expression like this:
<a th:href="@{/product/{id}(id=${product.sku})}">Product</a>
This can seem complicated, so let's look at the two steps that Thymeleaf does to complete the transformation:
-
the
${product.sku}
is the SKU property from theproduct
object (i.e., Thymeleaf does aproduct.getSku()
), and(id=${...})
means assign that property value to a temporary variableid
. -
The
/product/{id}
(which is a URI template) then gets the{id}
replaced at runtime from the temporaryid
variable from step 1.
So, if ${product.sku}
is 2, then Thymeleaf will transform /product/{id}
to the URL /product/2
and the href
would look like this:
<a href="/product/2">Product</a>
Parameterize Your Links¶
Since we want each order name cell to have both the name of the order and a link, we'll need to pull the th:text
out of the <td>
tag and into a <span>
.
The HTML that we want to be generated for order #1 that has the name Megan would be:
<td><a href="/coffee-order/1"><span>Megan</span></a></td>
-
Open the
all-coffee-orders.html
template and use the example from above and translate it into the appropriate Thymeleaf attributes. -
Go to
localhost:8080/
and then click on View all coffee orders -
Verify that clicking on a name link takes you to the specific page for that order.
Once you've completed the above steps,
check in with the instructor to review your code.
Bonus¶
-
You can use the "pre-processing" syntax to generate the
href
, which for this particular use case is easier:th:href="@{/coffee-order/__${coffeeOrder.id}__}"
In case you're interested, the documentation for the pre-processing syntax is here: http://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#preprocessing
Once you've completed the above steps,
check in with the instructor to review your code.