Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot render a computed property with Leaf in Vapor 3

Tags:

swift

vapor

leaf

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())
}
like image 421
Diiaablo Avatar asked Dec 05 '18 11:12

Diiaablo


People also ask

What is computed property in vue3?

Computed Property in Vue3 is used to declaratively describe a value that is dependent on other values. This feature of VueJS allows for transformations or computations based on our data. We can reuse the result of these computations and transformations in our DOM template. Computed properties remove the need for complex in-template expressions.

What is a computed property in JavaScript?

Think of a computed property as declaratively describing how to derive a value based on other values - its only responsibility should be computing and returning that value. Later in the guide we will discuss how we can perform side effects in reaction to state changes with watchers. The returned value from a computed property is derived state.

What are the dependencies of a computed property?

A computed property’s dependencies are reactive values that are used to determine the value of the computed property. If none of these dependencies change, the cached value will be returned. If the reactive values change, it will trigger the computed property to re-compute the modified value.

What is the derived state of a computed property?

The returned value from a computed property is derived state. Think of it as a temporary snapshot - every time the source state changes, a new snapshot is created.


1 Answers

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
    }
}
like image 58
Caleb Kleveter Avatar answered Oct 08 '22 04:10

Caleb Kleveter