
This video is only available to subscribers. Start a subscription today to get access to this and 484 other videos.
Nesting Templates and Partials
This episode is part of a series: Server-side Swift with Vapor.
1. Getting Started with Vapor 12 min |
2. Vapor Routing 14 min |
3. Leaf Templates 13 min |
4. Nesting Templates and Partials 8 min |
5. Vapor Demo: Tokenizr 21 min |
6. Setting up a Database with Fluent 19 min |
7. Creating, Updating, and Deleting Records with Fluent 19 min |
8. Vapor Futures 20 min |
9. Setting up Vapor with Postgresql 17 min |
10. UUID Primary Keys 13 min |
11. Timestamp Fields 4 min |
12. Refactoring to Protocols 12 min |
13. Parent Child Relationships and Foreign Keys 14 min |
14. Pivot Tables for Many to Many Relationships 14 min |
15. Vapor Controllers 15 min |
16. Decoding Request Parameters 9 min |
Use Functions for Multiple Routes
To share logic between multiple routes, we can extract our handler code into a function.
func getHello(_ req: Request) throws -> Future<View> {
let user = try? req.parameters.next(String.self)
let context = UserPage(user: user, categories: [
"Articles", "Recipes", "Reviews"
])
return try req.view().render("hello", context)
}
This function needs to match the signature that route blocks expect. It must accept a single Request
parameter and define the return value explicitly. It also must be a throws
function.
Then we can define multiple routes that use this function.
router.get("hello", use: getHello)
// hello/ben
router.get("hello", String.parameter, use: getHello)
Looping over Content in Leaf Templates
To display our list of categories in Leaf, we can use the #for
statement:
<ul>
#for(category in categories) {
<li>#(category)</li>
}
</ul>
Defining a Master Template
Our pages probably want to share quite a bit of layout, styles, and javascript. For this we can define a master template and cut out sections that we can inject the current page's content into.
First, we create a master.leaf
template:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>#get(title)</title>
<style media="screen">
body {
font-family: 'Helvetica', sans-serif;
font-size: 18px;
color: #444;
background-color: #eee;
}
</style>
</head>
<body>
#get(content)
</body>
</html>
Note that we have defined 2 dynamic sections here. Leaf will look for variables called title
and content
that our templates must provide.
We can update our hello.leaf
template to use this master template like this:
#set("title") { Hello Leaf Templates }
#set("content") {
<h1>Hello from Leaf!</h1>
#if(user) {
<h2>You are logged in as #(user)</h2>
<ul>
#for(category in categories) {
<li>#(category)</li>
}
</ul>
} else {
<h2>You are not logged in</h2>
}
}
#embed("master")
Extracting Partials
If we want to break down our template into reusable sections, we can move those into their own templates, which are called partials.
I'm going to use a Rails convention and prefix partials with an underscore to make it obvious which templates are intended to be rendered by the router, and which ones are just embedded within other templates.
Let's create _categories.leaf
:
<h3>Categories</h3>
<ul>
#for(category in categories) {
<li>#(category)</li>
}
</ul>
Then we can update hello.leaf
to embed this:
...
#if(user) {
<h2>You are logged in as #(user)</h2>
#embed("_categories")
}
...