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