Trabalhando com views - NodeJS e Express (parte 6)

Posted by uselessdev on 10/03/2017

Índice

Hey there!

No artigo anterior nós fizemos a edição e a exclusão de nossas tarefas, agora, precisamos criar nossa interface web, precisaremos fazer algumas mudanças no nosso código, mas é coisa bem simples, então vamos lá.

A primeira coisa que faremos é selecionar nossa engine view, ou seja, aquilo que vai ficar responsável por compilar e nos retornar o html da nossa página html, eu normalmente utilizo o Pug mas por questão familiaridade hoje iremos utilizar o handlebarsjs, então primeiro precisamos instalar ele,

1
npm install --save express-handlebars

Uma vez instalado precisamos dizer pra nossa aplicação qual engine vamos usar então, em bootstrap/app.js adicione o seguinte:

1
2
3
4
5
var hbs = require('express-handlebars')
// Antes do congign
app.engine('handlebars', hbs({defaultLayout: 'main'}))
app.set('view engine', 'handlebars')

Dessa forma precisaremos criar nossos arquivos como main.handlebars, mas escrever .hbs é mais simples, então, vamos fazer uma modificação:

1
2
3
4
5
app.engine('.hbs', hbs({
defaultLayout: 'main',
extname: '.hbs'
}))
app.set('view engine', '.hbs')

Agora vamos criar nosso layout principal e nossa home, views/layouts/main.hbs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tasklist - NodeJS e Express</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
{{{body}}}
</body>
</html>

views/home.hbs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<div class="container">
<div class="col-md-6 col-md-offset-3">
<div class="page-header">
<h1>
Tarefas
<a class="btn btn-primary pull-right" href="/create">Adicionar tarefa</span></a>
</h1>
</div><!-- /.page-header -->
<table class="table table-hover">
<thead>
<th width="25px"><strong>#</strong></th>
<th width="55%"><strong>Titulo</strong></th>
<th colspan="2"><strong>Status:</strong></th>
</thead>
<tbody>
{{#each tasks}}
<tr>
<td><span>{{_id}}</span></td>
<td><span>{{title}}</span></td>
{{#if status}}
<td>Concluído</td>
{{else}}
<td>Não concluído</td>
{{/if}}
<td width="100px">
<a class="btn btn-info" href="/edit/{{_id}}"><span class="fa fa-pencil"></span></a>
<a class="btn btn-danger" href="/task/{{_id}}"><span class="fa fa-trash"></span></a>
</td>
</tr>
{{/each}}
</tbody>
</table>
</div><!-- /.col-sm-4 -->
</div><!-- /.container -->

Bem agora já temos nossa view, precisamos retornar dados do nosso controller, então vamos fazer o seguinte no nosso controllers/tasks.js

1
2
3
4
index: function (request, response) {
let tasks = Task.all()
response.render('home', {tasks: tasks.data})
},

Aqui removemos, nosso response.json(Task.all()) e adicionamos, um response.render, bem, o método render, renderiza um template pelo nome, no caso, home.hbs e outro argumento, é o que queremos passar pro template como váriável, no caso: tasks, mas além da interface web ainda queremos deixar a possíbilidade de esses dados serem consumidos via API, então ainda no método index vamos fazer uma alteração.

1
2
3
4
5
6
7
8
9
10
11
12
index: function (request, response) {
let tasks = Task.all()
response.format({
json: function () {
return response.json(tasks)
},
html: function () {
return response.render('home', {tasks: tasks.data})
}
})
},

Isso é conhecido como, Content Negotiation, ou seja, dependendo do accept da sua requisição você pode enviar dados com formatos diferentes, e de formas diferentes.

Bem, por enquanto é isso, no próximo artigo, nós criaremos as próximas telas que serão: Cadastro e Edição.

Até mais.

Próximo artigo


Comentários: