When working with web pages, you will almost certainly want to share a considerable amount of HTML. By nesting templates inside of master templates, we can share common HTML structure, layout, and share styles and scripts. We will see how to define sections that can be customized inside of your templates, as well as how to extract common components into partials that you can embed inside of other templates.
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") } ...