Vapor 4 Per object subordinate views/templates in Leaf?

167 Views Asked by At

.nameJust getting into Vapor and I think I've got the basics down relatively well. But I have a design model for a page that has me stumped.

I have a simple index of servers that displays in a table just fine. What I want to do in on a per server basis lookup and count the number of related entries of another type of object, say logs, filtered by date.

It seems to be that the obvious solution is to use #embed for the summary data, but I can't find the way to send parameters to the sub template as from what I understand from the docs, the #embed inherits the context from the source page, but I want the #embed to run a filtered query based on the current server in the #for loop.

//
//  WebsiteController.swift
//

import Vapor
import Leaf

struct WebsiteController: RouteCollection {
    func boot(routes: RoutesBuilder) throws {
        routes.get(use: indexHandler)
    }
    func indexHandler(_ req: Request) -> EventLoopFuture<View> {
        Server.query(on: req.db).all().tryFlatMap { servers in
            let serversData = servers.isEmpty ? nil : servers
            let context = IndexContext(
                title: "Servers",
                servers: serversData
            )
            return req.view.render("index", context)
        }
        
    }
}

struct IndexContext: Encodable {
    let title: String
    let servers: [Server]?
}

index.leaf

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">

  <title>#(title) | Listing</title>
</head>

<body>
  <h1>#(title)</h1>
  
  #if(servers):
  <table>
    <thead>
        <tr>
            <th>Name #count(servers)</th>
            <th>Address</th>
            <th>Logs</th>
            <th>Logs Today</th>
        </tr>
    </thead>
    <tbody>
    #for(server in servers):
        <tr>
            <td>#(server.name)</td>
            <td>#(server.ip_address)</td>
            <td></td>
            <td></td>
        </tr>
    #endfor
    </tbody>
  </table>
  
#else:
<h2>No servers registered</h2>
#endif
</body>
</html>

Any ideas on how to accomplish this?

1

There are 1 best solutions below

1
On BEST ANSWER

Leaf at its core is a pretty simple templating engine. This keeps its implementation simple and reduces the potential for security issues so if you want to do more than an if statement inside the for loop you'll either need to do this logic in Swift and pass it to your Leaf context, or write a custom tag.