Templates
med
Webbserverprogrammering 1

+ använda statiska resurser + redirects
Som templatemotor ska vi använda JavaScript templating (EJS) vilken hjälper oss att rendera HTML-sidor med dynamisk information från JavaScript. D.v.s med en templatemotor kan vi generera delar av HTML-koden och skriva ut innehåll från variabler i JavaScript, så att sidornas innehåll blir dynamiskt.
Templatemotor
Det finns även andra templatemotorer som Pug (https://pugjs.org/) och Handlebars (https://handlebarsjs.com/)
npm install ejs
Installera EJS
const app = express(); // Efter denna
// Använda EJS som templatemotor
app.set('view engine', 'ejs');
EJS med Express
Vi behöver säga tll Express att använda EJS som templatemotor, eftersom Express har stöd för flera olika.
app.js
<h1>Dagens datum</h1>
<p>Datum och tid för idag: <%= date %></p>
Skapa en vy-fil
Eller kallas även template-fil
Måste finnas i mappen views/ och ha filändelsen .ejs
views/exempel.js
EXEMPEL
Innanför dessa krumelurer "spottar" vi ut det dynamiska värdet för variabeln "date"
Hur? =>
router.get("/", function (request, response) {
let todayDate = new Date();
response.render("exempel", {date: todayDate);
});
En route som som renderar en vy
routes/exempelRoute.js
EXEMPEL
Filen som variabeln "date" ska renderas till. Express förstår att den ligger i "views" och är en .ejs-fil
Variabeln som ska "skickas" till filen
1. Använda Partials
Dela upp vår layout i delar för att inte repetera kod. Inom backend är det vanligt att dela in i minst i delare header och footer och lägga i varsin fil för att sedan inkludera i andra filer. Stor fördel att om vi exempelvis behöver ändra något i header så gör vi det endast i en fil och inte flera!
Partials
så kallas denna teknik
Vi använder CSS-ramverket Boostrap för att förenkla styling


Dela upp vår layout
<!-- Inkluderar filen i header.ejs -->
<%- include("./../partials/header") %>
<!-- SIDANS HTML -->
<!-- Inkluderar filen i footer.ejs -->
<%- include("./../partials/footer") %>
Dela upp vår layout
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/style.css">
<title>17 TE Blog</title>
</head>
<body>
views/partials/header.ejs
</body>
</html>
views/partials/footer.ejs
COPY-PASTE!
Boostrap CDN
Egen CSS
2. Skapa våra vyer för att hantera inlägg
Skapa våra vyer för att hantera inlägg

Routenamn | Endpoint | HTTP metod | Beskrivning |
---|---|---|---|
Index | /posts | GET | Visar alla inlägg |
New | /posts/new | GET | Formulär för att skapa nytt inlägg |
Show | /posts/:id | GET | Visar specifikt inlägg |
Edit | /posts/:id/edit | GET | Formulär för att upddatera inlägg |
views/index.ejs
<%- include("./../partials/header") %>
<div class="container">
<header class="jumbotron">
<div>
<h1>Välkommen till en blog om inget särskilt</h1>
<p>Här kommer det postas irrevelanta saker i kursen Webbserverprogrammering 1</p>
<p>
<a class="btn btn-primary btn-lg" href="/posts/new">Skapa nytt inlägg</a>
</p>
</div>
</header>
<div class="row text-center" style="display: flex; flex-wrap: wrap;">
<!-- HÄR SKA VI LOOPA GENOM ALLA INLÄGG -->
<div class="col-md-3 col-sm-6">
<div>
<div class="thumbnail">
<h4> <!-- HÄR SKA VI VISA VARJE INLÄGGS TITEL --></h4>
<!-- HÄR SKA VI HA VARJE INLÄGGS BILDADRESS -->
<img src=#>
</div>
</div>
<div class="caption">
<h4><!-- HÄR SKA VI VISA VARJE INLÄGGS TITEL --></h4>
</div>
<p>
<!-- HÄR BEHÖVER VI INLÄGGES ID SÅ ATT VI KAN KOMMA TILL SIDAN FÖR SPECIFIKT INLÄGG -->
<a href=# class="btn btn-primary">Mer info</a>
</p>
</div>
<!-- HÄR AVSLUTAR VI LOOPEN -->
</div>
</div>
<%- include("./../partials/footer") %>
COPY-PASTE!
views/new.ejs
<%- include("./../partials/header") %>
<div class="container">
<div class="row">
<h1 style="text-align: center">Skapa ett nytt inlägg</h1>
<div style="width: 30%; margin: 25px auto;">
<form action="/posts" method="POST">
<div class="form-group">
<input class="form-control" type="text" name="title" placeholder="titel">
</div>
<div class="form-group">
<input class="form-control" type="text" name="image" placeholder="bildadress">
</div>
<div class="form-group">
<input class="form-control" type="text" name="body" placeholder="innehåll">
</div>
<div class="form-group">
<button class="btn btn-lg btn-primary btn-block">Skicka!</button>
</div>
</form>
<a href="/posts">Gå tillbaka</a>
</div>
</div>
</div>
<%- include("./../partials/footer") %>
COPY-PASTE!
Egentligen ingen dynamisk html här, men kanske i framtiden?
views/show.ejs
<%- include("./../partials/header") %>
<div class="container">
<div class="row">
<div class="col-md-3">
<p class="lead">En blog om inget särskilt</p>
<div class="list-group">
<li class="list-group-item active">Info 1</li>
<li class="list-group-item">Info 2</li>
<li class="list-group-item">Info 3</li>
</div>
</div>
<div class="col-md-9">
<div class="thumbnail">
<!-- HÄR SKA VI LÄGGA IN DET SPECIFKA INLÄGGETS BILDLÄNK -->
<img class="img-responsive" src=#>
<div class="caption-full">
<h4><a> <!-- INLÄGGETS TITEL --></a></h4>
<p></p><!-- INLÄGGETS BODY (INNEHÅLL) --></p>
</div>
<!-- HÄR SKA VI LÄGGA IN DET SPECIFKA INLÄGGETS ID FÖR ATT KUNNA UPPDATERA ELLER TA BORT SPECIFIKT INLÄGG -->
<a class="btn btn-xs btn-warning" href="/posts/ID/edit">Uppdatera</a>
<form id="delete-form" action="/posts/ID?_method=DELETE" method="POST">
<button class="btn btn-xs btn-danger">Ta bort</button>
</form>
</div>
<!-- HÄR SKULLE MAN EV KUNNA LÄGGA IN KOMMENTARER I FRAMTIDEN -->
</div>
</div>
</div>
<%- include("./../partials/footer") %>
COPY-PASTE!
views/edit.ejs
<%- include("./../partials/header") %>
<div class="container">
<div class="row">
<h1 style="text-align: center">Uppdatera
<!-- INLÄGGETS TITEL -->
</h1>
<div style="width: 30%; margin: 25px auto;">
<!-- ERSÄTT # MED INLÄGGETS ID -->
<form action="/posts/ID?_method=PUT" method="POST">
<div class="form-group">
<input class="form-control" type="text" name="post[title]" placeholder="titel"
value="#">
</div>
<div class="form-group">
<!-- ERSÄTT # MED INLÄGGETS BILDADRESS -->
<input class="form-control" type="text" name="post[image]" placeholder="bildadress"
>value="#">
</div>
<div class="form-group">
<!-- ERSÄTT # MED INLÄGGETS BODY (INNEHÅLL) -->
<input class="form-control" type="text" name="post[body]" placeholder="innehåll"
value="#">
</div>
<div class="form-group">
<button class="btn btn-lg btn-primary btn-block">Skicka!</button>
</div>
</form>
<a href="/posts">Gå tillbaka</a>
</div>
</div>
</div>
<%- include("./../partials/footer") %>
COPY-PASTE!
3. Rendera data till våra vyer
Rendera alla inlägg
// Funktion för att hämta alla inlägg
exports.getPosts = async function (request, response) {
const allPosts = await Post.find();
// TODO: Felhantering
response.render("posts/index", { posts: allPosts });
}
controllers/postController.js
Rendera ett inlägg
// Funktion för att hämta ett inlägg utifrån id
exports.getPost = async function (request, response) {
let id = request.params.id;
const foundPost = await Post.findById(id);
// TODO: Felhantering
response.render("posts/show", { post: foundPost });
};
controllers/postController.js
Rendera ett inlägg till edit-sidans formulär
/* Funktion för att visa specifikt inlägg på sidan för att
visa ett formulär för att uppdatera specifikt inlägg */
exports.editPost = async function (request, response) {
let id = request.params.id;
const foundPost = await Post.findById(id);
// TODO: Felhantering
response.render("posts/edit", { post : foundPost});
}
controllers/postController.js
Rendera vyn för att visa ett formulär för att skapa inlägg
// Visa formulära för att skapa inlägg
router.get("/new", function (request, response) {
response.render("posts/new");
});
routes/postRoutes.js
4.Redirect
Att skickas till annan url
Skickas till /posts när ett inlägg skapats
// Funktion för att skapa ett inlägg
exports.createPost = async function (request, response) {
const newPost = await Post.create(request.body);
// TODO: Felhantering
response.redirect("/posts");
}
controllers/postController.js
Skickas till /posts när ett inlägg tagits bort
// Funktion för att ta bort ett inlägg
exports.deletePost = async function (request, response) {
const post = await Post.findByIdAndDelete(request.params.id);
if (!post) {
return response.status(400).json({
success: false
});
}
response.redirect("/posts");
}
controllers/postController.js
5. Använda statiska resurser i Express
På en webbplats är det vanligt med statiska resursers såsom bilder, stylesheets och Javascript-filer som används till klientsidan. Det kan också vara fler html-sidor som ska vara statiska och inte dynamiska.
Statiska resurser brukar man lägga i en mapp public.

Sätta upp statiska resurser i Express
// Använda EJS som templatemotor för express
app.set('view engine', 'ejs');
/* Säga till Express var våra statiska
filer ska ligga */
app.use(express.static("public"));
6. Dags att EJS:a! Spotta ut vår data i våra vy-filer
EJS syntax
<%# Kommentarer! %>
<p>Datum och tid för idag: <%= date %></p>
Variabler
Kommentarer
EJS syntax
<h1>Our Post Page!</h1>
<ul>
<% for(let i = 0; i < posts.length; i++) { %>
<li><%= posts[i].title %> - <%= posts[i].name %> </li>
</ul>
<% } %>
<h1>Hey <%= username.toUpperCase() %>, Welcome to Our site</h1>
<% if(username.toLowerCase() === "danny"){ %>
<p>Danny you are Beautiful!</p>
<% } else { %>
<p>You are not Danny, you are not Beautiful!</p>
<% } %>
If-satser
Loopar
Templates med EJS
By Sandra Larsson
Templates med EJS
Att rendera HTML med dynamiska värden med templatemotorn EJS.
- 145