Edge templates
Returning HTML as a string from a controller is awkward. For pages AdonisJS has the Edge template engine: a template is a file with HTML and data inserts, and the controller only passes data into it. Templates live in resources/views/ and have the .edge extension.
Creating a template
node ace make:view pages/posts/indexThe command creates an empty file resources/views/pages/posts/index.edge. Write in it:
{{-- resources/views/pages/posts/index.edge --}}
<h1>{{ title }}</h1>
<p>Total posts: {{ posts.length }}</p>Double curly braces print the value of a JavaScript expression. {{-- ... --}} is an Edge comment, it does not reach the HTML.
Rendering a template from a controller
// app/controllers/posts_controller.ts
import type { HttpContext } from '@adonisjs/core/http'
export default class PostsController {
async index({ view }: HttpContext) {
const posts = [
{ id: 1, title: 'First post' },
{ id: 2, title: 'Hello, AdonisJS' },
]
return view.render('pages/posts/index', { title: 'Blog', posts })
}
}view.render takes the template path relative to resources/views without the extension, and an object with data. The object's keys become template variables. Open /posts — you see the heading "Blog" and the line "Total posts: 2".
Conditions
{{-- resources/views/pages/posts/index.edge --}}
@if(posts.length === 0)
<p>No posts yet.</p>
@elseif(posts.length === 1)
<p>One post.</p>
@else
<p>Posts: {{ posts.length }}</p>
@endEdge tags start with @, and a block is closed with @end.
Loops
The @each tag iterates over an array. The @else branch inside it runs when the array is empty:
{{-- resources/views/pages/posts/index.edge --}}
<ul>
@each(post in posts)
<li>
<a href="{{ route('posts.show', { id: post.id }) }}">{{ post.title }}</a>
</li>
@else
<li>No posts yet.</li>
@end
</ul>The page shows a list of titles, each one a link to the post. You get the item index with @each((post, index) in posts).
Escaping
Edge escapes everything printed with {{ }}: if a post title contains <script>, it is shown as text, not executed. When HTML must be printed as is, for example post text from a trusted editor, use triple braces:
{{-- resources/views/pages/posts/show.edge --}}
<article>{{{ post.bodyHtml }}}</article>Common mistake
Triple braces around text a user typed open the door to an XSS attack: someone else's script runs in every visitor's browser. Print user data only with {{ }}, and keep {{{ }}} for HTML you built and cleaned yourself.