Reputation: 176
I've been trying to render a computed property using the templating engine Leaf with Vapor 3, but so far no luck. If the same property is stored, everything works fine. If I make it computed, nothing is displayed in the web page. I can understand the reasons why such solution wouldn't be working, but I'd like to know if there's any way to make it working.
Code for the element to render:
struct SocialLinkContext: Encodable, CSSStyleable {
let hyperlinkURI: String
let classes: [String]
//let styleClasses: String
init(hyperlinkURI: String, classes: [String]) {
self.hyperlinkURI = hyperlinkURI
self.classes = classes
//self.styleClasses = classes.joined(separator: " ")
}
//Seems not to be supported by Leaf
var styleClasses: String {
return self.classes.joined(separator: " ")
}
}
Part of the main_page.leaf file:
...
<div class="row banner">
<div class="banner-text">
<h1 class="responsive-headline">Hello, world!</h1>
<hr />
</div>
#embed("social_links")
</div>
...
The social_links.leaf file:
<ul class="social">
#for(socialContext in socialLinks) {
<li>
<a href="#(socialContext.hyperlinkURI)">
<i class="#(socialContext.styleClasses)"></i>
</a>
</li>
}
</ul>
The PersonalPageContext to be passed to the View Renderer:
struct PersonalWebPageContext: Encodable {
...
let socialLinks: [SocialLinkContext] = [...]
...
}
And finally, the PersonalWebPageViewController controller:
private func serveWebPage(req: Request) throws -> Future<View> {
return try req.view().render("main_page", PersonalWebPageContext())
}
Upvotes: 10
Views: 500
Reputation: 11494
This is because Leaf uses Codable
to convert your context type to data that Leaf can use. Now by default, Codable
does not encode or decode computed properties. If you want to do that, you have to manually implement the encode(to:)
method.
struct SocialLinkContext: Encodable, CSSStyleable {
let hyperlinkURI: String
let classes: [String]
var styleClasses: String {
return self.classes.joined(separator: " ")
}
init(hyperlinkURI: String, classes: [String]) {
self.hyperlinkURI = hyperlinkURI
self.classes = classes
}
func encode(to encoder: Encoder)throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.hyperlinkURI, forKey: .hyperlinkURI)
try container.encode(self.classes, forKey: .classes)
try container.encode(self.styleClasses, forKey: .styleClasses)
}
enum CodingKeys: String, CodingKey {
case hyperlinkURI, classes, styleClasses
}
}
Upvotes: 11