Views
In Loco
, the processing of web requests is divided between a controller, model and view.
- The controller is handling requests parsing payload, and then control flows to models
- The model primarily deals with communicating with the database and executing CRUD operations when required. As well as modeling all business and domain logic and operations.
- The view takes on the responsibility of assembling and rendering the final response to be sent back to the client.
You can choose to have JSON views, which are JSON responses, or Template views which are powered by a template view engine and eventually are HTML responses. You can also combine both.
JSON views
As an example we have an endpoint that handles user login. When the user is valid we can pass the user
model into the LoginResponse
view (which is a JSON view) to return the response.
There are 3 steps:
- Parse, accept the request
- Create domain objects: models
- Hand off the domain model to a view object which shapes the final response
The following Rust code represents a controller responsible for handling user login requests, which handes off shaping of the response to LoginResponse
.
use crate::;
async
On the other hand, LoginResponse
is a response shaping view, which is powered by serde
:
use ;
use crate users;
Template views
When you want to return HTML to the user, you use server-side templates. This is similar to how Ruby's erb
works, or Node's ejs
, or PHP for that matter.
For server-side templates rendering we provide the built in TeraView
engine which is based on the popular Tera template engine.
ViewEngineInitializer
in initializers/view_engine.rs
which is also specified in your app.rs
. If you used the SaaS Starter, this should already be configured for you.
The Tera view engine takes resources from the new assets/
folder. Here is an example structure:
assets/
├── i18n
│ ├── de-DE
│ │ └── main.ftl
│ ├── en-US
│ │ └── main.ftl
│ └── shared.ftl
├── static
│ ├── 404.html
│ └── image.png
└── views
└── home
└── hello.html
config/
:
src/
├── controllers/
├── models/
:
└── views/
Creating a new view
First, create a template. In this case we add a Tera template, in assets/views/home/hello.html
. Note that assets/ sits in the root of your project (next to src/
and config/
).
find this tera template at assets/views/home/hello.html :
{{ /* t(key="hello-world", lang="en-US") */ }},
{{ /* t(key="hello-world", lang="de-DE") */ }}
Now create a strongly typed view
to encapsulate this template in src/views/dashboard.rs
:
// src/views/dashboard.rs
use *;
And add it to src/views/mod.rs
:
Next, go to your controller and use the view:
// src/controllers/dashboard.rs
use *;
use crate views;
pub async
Finally, register your new controller's routes in src/app.rs
;
Once you've done all the above, you should be able to see your new routes when running cargo loco routes
$ cargo loco routes
[GET] /_health
[GET] /_ping
[POST] /api/auth/forgot
[POST] /api/auth/login
[POST] /api/auth/register
[POST] /api/auth/reset
[POST] /api/auth/verify
[GET] /api/auth/current
[GET] /home <-- the corresponding URL for our new view
How does it work?
ViewEngine
is an extractor that's available to you vialoco_rs::prelude::*
TeraView
is the Tera view engine that we supply with Loco also available vialoco_rs::prelude::*
- Controllers need to deal with getting a request, calling some model logic, and then supplying a view with models and other data, not caring about how the view does its thing
views::dashboard::home
is an opaque call, it hides the details of how a view works, or how the bytes find their way into a browser, which is a Good Thing- Should you ever want to swap a view engine, the encapsulation here works like magic. You can change the extractor type:
ViewEngine<Foobar>
and everything works, becausev
is eventually just aViewRenderer
trait
Static assets
If you want to serve static assets and reference those in your view templates, you can use the Static Middleware, configure it this way:
static:
enable: true
must_exist: true
precompressed: false
folder:
uri: "/static"
path: "assets/static"
fallback: "assets/static/404.html"
In your templates you can refer to static resources in this way:
Customizing the Tera view engine
The Tera view engine comes with the following configuration:
- Template loading and location:
assets/**/*.html
- Internationalization (i18n) configured into the Tera view engine, you get the translation function:
t(..)
to use in your templates
If you want to change any configuration detail for the i18n
library, you can go and edit src/initializers/view_engine.rs
.
By editing the initializer you can:
- Add custom Tera functions
- Remove the
i18n
library - Change configuration for Tera or the
i18n
library - Provide a new or custom, Tera (maybe a different version) instance
Using your own view engine
If you do not like Tera as a view engine, or want to use Handlebars, or others you can create your own custom view engine very easily.
Here's an example for a dummy "Hello" view engine. It's a view engine that always returns the word hello.
// src/initializers/hello_view_engine.rs
use ;
use ;
use Serialize;
;
;
To use it, you need to add it to your src/app.rs
hooks:
// src/app.rs
// add your custom "hello" view engine in the `initializers(..)` hook