Introduction to Web Programming in F# with Giraffe – Part 3
Introduction
In this series we are investigating web programming with Giraffe and the Giraffe View Engine plus a few other useful F# libraries.
In the last post, we created a simple API for managing a Todo list. In this post, we are going to start our journey into HTML views with the Giraffe View Engine.
If you haven't already done so, read the previous posts in this series.
Getting Started
We are going to use the project we created for the last post and add to it.
Running the Sample Code
In the Terminal, type the following to run the project:
dotnet run
Go to your browser and type in the following Url:
https://localhost:5001
You should see some text.
Now try the following Uri and you should see some Json returned:
https://localhost:5001/api
Our Task
We are going to create a simple HTML view of a Todo list. In this post, we will concentrate on getting things on the screen. We will wire in to the backend in the next post.
Rather than rely on my HTML/CSS skills, we are going to start with a pre-built sample: The ToDo list example from w3schools:
https://www.w3schools.com/howto/howto_js_todolist.asp
Configuration
Add a new folder to the project called WebRoot and add a couple of files to the folder: main.js and main.css.
Open the .fsproj file and add the following snippet:
The final step to enable these files to be used is to edit the main function:
We have added a couple of lines to tell the code where the WebRoot folder is and have passed that path to a helper function UseWebRoot
.
That's the end of the configuration but we need to copy the code from the w3schools site for the css and javascript to our files.
Converting HTML To Giraffe ViewEngine
If you've never seen a DSL like the Giraffe View Engine, it is going to be a bit of a shock but bear with it because it really makes sense!
Let's start with a basic HTML page:
If we convert it to Giraffe View Engine format, we get:
Most tags have two lists, one for styling and one for content. Some tags, like input
, only take the style list. The Giraffe ViewEngine is a Domain Specific Language (DSL) that generates XHTML from F#.
To create the original HTML view, we would call:
This approach is very different to most view engines which rely on search and replace but are primarily still HTML. The primary advantage of the Giraffe View Engine approach is that you get full type safety when generating views and can use the full power of the F# language.
ToDo Snippet
Our ToDo HTML snippet below has to be converted into Giraffe ViewEngine code:
Let's create a new function to generate our ToDo HTML snippet:
We are nearly ready to run: We only need to tell the router about our new handler. Change the first route in webApp from:
If you now run the app using dotnet run
and click on the link (mine goes to https://localhost:5001
), you will see the ToDo app.
Next Stage
Rather than hard code the list of ToDos in the view generation, we can load it in on the fly:
We created a simple list of ToDos, a small helper function to style the list item, and used a list comprehension to generate the items displayed in the list.
The code from this post can be found here:
https://gist.github.com/ianrussellsoftwarepark/13569e9a930086d69082481dabebb1f8
I encourage you to have a look at the documentation and source code for the Giraffe View Engine.
https://github.com/giraffe-fsharp/Giraffe.ViewEngine#documentation
In the next post, we will investigate tying the frontend and backend together.
If you like the Giraffe View Engine, but don't like writing JavaScript, you should investigate the SAFE Stack where everything is F#.
Summary
I hope that you found this introduction to HTML views in F# with Giraffe and the Giraffe View Engine useful and interesting. We have only scratched the surface of what is possible with Giraffe for creating web pages.
In the next post we will start to extend the functionality we covered in this post to wire up the frontend and backend.
If you have any comments on this series of posts or suggestions for new ones, send me a tweet (@ijrussell) and let me know.