Tutorial: How to useΒ Leaf

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 😊

1. Create a newΒ project

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
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 🀜🏻 πŸ€›πŸ» ).

2. Generate the XcodeΒ project

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.0
import PackageDescription
let 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/

3. Configure your project to be able to useΒ Leaf

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

import LeafProvider // added
extension 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",
...

}

4. Create your firstΒ template

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>

5. Implement a route to serve theΒ view

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

import Vapor
extension 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

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! πŸ™ŒπŸ»


6. BONUS: Passing data to theΒ view

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

import Vapor
extension 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 πŸŽ‰Β !!


Thank you a lot for reading! If you have any suggestions or improvements - Let me know! I would love to hear from you! 😊

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.