Tutorial: How to use Leaf

Martin Lasek
Sep 24, 2017 Β· 5 min read
Image for post
Image for post

Yeey time to learn leaf β€” a templating language to easily generate views!

You can find the result of this tutorial on github here

This tutorial is a natural follow-up of How to set up a Vapor 2 project. You can either go for that tutorial first and come back or just skip it and read on 😊

Vapor toolbox is so nice it let’s you easily create new projects using any git-repo as a template. Since we will build upon the outcome of the aforementioned tutorial, we will create a new project using it as a template:

vapor new yourProjectName --template=vaporberlin/my-first-route --branch=vapor-2

NOTE: You can see what vapor toolbox is all capable of by typing vapor --help in your terminal :)

Our command will create a project with the name yourProjectName using my-first-route from vaporberlin as a template (thanks vapor toolbox 🀜🏻 πŸ€›πŸ» ).

Before we generate an Xcode project we would have to add the Leaf-Provider as a dependency and also change the package name within Package.swift:

// swift-tools-version:4.0import PackageDescriptionlet package = Package(
name: "yourProjectName", // changed
products: [
.library(name: "App", targets: ["App"]),
.executable(name: "Run", targets: ["Run"])
],
dependencies: [
.package(url: "https://github.com/vapor/vapor.git", .upToNextMajor(from: "2.1.0")), // don't forget that comma πŸ˜‰
.package(url: "https://github.com/vapor/leaf-provider.git", .upToNextMajor(from: "1.1.0")) // added
],
targets: [
.target(name: "App", dependencies: ["Vapor", "LeafProvider"],
exclude: [
"Config",
"Public",
"Resources",
]
),
.target(name: "Run", dependencies: ["App"]),
.testTarget(name: "AppTests", dependencies: ["App", "Testing"])
]
)

Now in the terminal at the root directory yourProjectName/ execute:

vapor update -y

It may take a bit fetching the dependency, generating the Xcode project and opening it for you. But when done you should have a project structure like this:

yourProjectName/
β”œβ”€β”€ Package.swift
β”œβ”€β”€ Sources/
β”‚ β”œβ”€β”€ App/
β”‚ β”‚ β”œβ”€β”€ Routes/
β”‚ β”‚ β”‚ └── Routes.swift
β”‚ β”‚ └── Setup/
β”‚ β”‚ β”œβ”€β”€ Config+Setup.swift
β”‚ β”‚ └── Droplet+Setup.swift
β”‚ └── Run/
β”œβ”€β”€ Tests/
β”œβ”€β”€ Config/
β”œβ”€β”€ Public/
β”œβ”€β”€ Dependencies/
└── Products/

Our first step is to add the LeafProvider in our Setup/Config+Setup.swift:

import LeafProvider // addedextension Config {
public func setup() throws {
try setupProviders()
try setupPreparations()
}
/// Configure providers
private func setupProviders() throws {
try addProvider(LeafProvider.Provider.self) // added
}
/// Add all models that should have their
/// schemas prepared before the app boots
private func setupPreparations() throws {}
}

Next is to set leaf as a view renderer anywhere within Config/droplet.json:

{
...
"//": "The type of view renderer that drop.view will use",
"//": "leaf: Pure Swift templating language created for Vapor.",
"//": "static: Simply return the view at the supplied path",
"view": "leaf",
...

}

Our view renderer leaf is expecting a directory called Resources/ and right underneath it a directory called Views/ to hold all view-files. So you will end up with a structure like the following: yourProjectName/Resources/Views/

NOTE: They have to be directories (blue folder) and not groups (yellow folder). I created them in terminal with mkdir -p Resources/Views

You may have to re-generate your Xcode project with vapor xcode -y in order to let Xcode see your new directories. When done in Resources/Views/ create a new file named myview.leaf with following code:

<!DOCTYPE html>
<html>
<head>
<title>Leaf</title>
</head>
<body> <h1> My first leaf template! </h1> </body>
</html>

In your Routes/Routes.swift add a new route, let’s call it.. πŸ€”

import Vaporextension Droplet {
func setupRoutes() throws {
get("name") { req in
return "Ethan Hunt"
}
get("age") { req in
return "\(23)"
}
get("json") { req in
return try JSON(node: ["name": "Martin J. Lasek", "age": 26])
}
get("view") { req in
return try self.view.make("myview")
}
}
}

If you now hit cmd + r or the play button on top of Xcode, it will start the application. The console in Xcode tells you where. For me it’s 127.0.0.1/8001

Image for post
Image for post
Note: make sure to select Run as a scheme next to your button before running the app

NOTE: The port from where you can reach your app is defined within Config/server.swift β€” you can change it as you like and re-run the app :)

If you now fire up 127.0.0.1:8001/view in your browser you will get a view served using Leaf as a templating language! πŸ™ŒπŸ»


It’s super easy to pass data into a view. And this is how it looks like:

import Vaporextension Droplet {
func setupRoutes() throws {
get("name") { req in
return "Ethan Hunt"
}
get("age") { req in
return "\(23)"
}
get("json") { req in
return try JSON(node: ["name": "Martin J. Lasek", "age": 26])
}
get("view") { req in
return try self.view.make("myview")
}
get("bonus") { req in
return try self.view.make("mydataview", ["name": "Taichi"])
}
}
}

If you now create a new file in Resources/Views/ called mydataview.leaf you can access the passed data in it like so:

<!DOCTYPE html>
<html>
<head>
<title>Leaf</title>
</head>
<body>
<h1> You rule #(name)! </h1>
</body>
</html>

Now re-run your application and fire up 127.0.0.1:8001/bonus :D!
That’s it! You successfully implemented a leaf template project πŸŽ‰ !!


Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium β€” and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store