Templating

Sometimes we want to put HTML into our page after the page has rendered. Perhaps we need user input to create something, rather than show/hiding it. Perhaps we want to call a server to get data that matches the user's stipulations, and then display that data in HTML.

Demo

How it's done...

The process comes in a two parts:

  1. Construction of the new HTML
  2. Insertion into the page

Insertion

Insertion (part 2) is quite easy:

//natural javascript
//replace content
document.getElementById('target').innerHTML = "<p>Hello World!</p>";
//repeatedly add content
document.getElementById('target').innerHTML += "<p>Hello World!</p>";


//jQuery
//replace content
$('#target').html('<p>Hello World!</p>');
//repeatedly add content
$('#target').append('<p>Hello World!</p>');

Manufacture

The manufacture (part 1), however, is a little more tricky! To create new HTML we could just use javascript normally:

💩
//in native js
var profileFrag = document.createElement('DIV');
profileFrag.className = "profile";
profileFrag.innerHTML = "<dl><dt>Name:</dt><dd>" + person.name + "</dd><dt>Age:</dt><dd>" + person.age + "</dd><dt>Height:</dt><dd>" + person.height + "</dd></dl>"
document.getElementById("target").innerHTML = profileFrag;

//in jQuery
$('#target').html('<div class="profile"><dl><dt>Name:</dt><dd>' + person.name + '</dd><dt>Age:</dt><dd>' + person.age + '</dd><dt>Height:</dt><dd>' + person.height + '</dd></dl></div>');

As you can see, that's not very readable or maintainable. These days we use a system called 'Client-side Templating' that abstracts all that difficulty away! There are lots of templating libraries out there, but we are going to use Handlebars...

A Quick Guide to using Handlebars

  1. Include the Handlebars script in the page (CDN or local)
  2. Insert templates into the page using script tags, like:

    <script id="my-template" type="text/x-handlebars-template"></script>
    1. The type attribute must be set to text/x-handlebars!!
    2. Also, your template script block should have an id set on it in order to find and use the template...
  3. Inside those tags you add Handlebars template code that looks like:

    <script id="my-template" type="text/x-handlebars-template">
      <div class="entry">
        <h3>{{title}}</h3>
        <div class="body">
          <p>{{body}}</p>
        </div>
      </div>
    </script>

    The {{<something>}}s are where we will insert data which is relevant to the piece of HTML we are creating.

  4. The next step is to get hold of the template markup and use it. To do this we need to copy it, and then Handlebars needs to 'compile' it.

    Compilation is when Handlebars takes the contents of that script block and turns it into a function that outputs html. The function accepts an argument (which is an object) that contains any extra data required to manufacture that particular piece of HTML.

    Once stored, you can use a template repeatedly, say for rendering a list of products, by calling that function and passing the data for a different product each time. We refer to this data as the 'context' in which the template is rendered.

    var source   = $("#my-template").html(); //Gets template markup from inside the script tag
    var template = Handlebars.compile(source); //Returns a function we'll use to create HTML chunks
  5. Next you must get hold of the data that you'll use to render that particular piece of html. (The context) e.g.:
    var data = {title: "New HTML", body: "This is my templated content!"};
  6. You then call the template function we created above, passing the data. This will return the new HTML:

    var html = template(data);

    This produces the HTML:

    <div class="entry">
      <h3>New HTML</h3>
      <div class="body">
        <p>This is my templated content!</p>
      </div>
    </div>
  7. Now insert it into the page:
    $('#targetArea').html(html);

Exercise:

Build your own templates:

  1. Just HTML
  2. HTML from template with data
  3. HTML from precompiled template with data

Inject them here:

AJAX

For this next section we'll require npm and the use of your command line.

To find your command line on mac:

  1. Press CMD + space to bring up your spotlight program.
  2. Type terminal into spotlight and at some point it will auto-suggest the terminal application.
  3. Hit return or click on it to activate.

To find your command line on windows 10 (which sadly isn't as good):

  1. press the start button
  2. then type command prompt. At some point it will auto-suggest the terminal application.
  3. Hit return or click on it to activate.

npm is node.js' package manager. If you type npm -v into your command line and hit return and get a message saying that npm is not recognised, then you'll need to install node.js from https://nodejs.org/en/download/

To use ajax reliably you need your page to be on a server: This can be a local server (i.e. one that is running on your machine) or a remote server. To create a quick and easy local server, I recommend httpster. Install it globally using npm: Type npm i -g httpster into your command line and hit return.

To start the server, navigate on the command line into the folder that this page is in and the simply type httpster and hit return. You will instructed to browse to something like http://localhost:3333: Do so.

What AJAX does

AJAX stands for Asynchronous Javascript and XML. The internet was first designed to move between static documents. You moved from page to page and any changes would be shown in the next page. In the late 1999 Microsoft added an ability for Internet Explorer to call out to a server for more information without refreshing the page. This is known as asynchronous.

AJAX allows us to call out to servers (including our own) for resources after the page has been loaded. We can call for actual html files (generally these are not whole pages and are known as 'partials') and insert them into our current page; specific data files (JSON or, less commonly, XML), or; we can call the server, using a non-specific URI and ask for a response (which is typically JSON)

Introducing JSON

JSON is a 'transport language'. It stands for 'JavaScript Object Notation'. It allows the transport of JavaScript objects between locations.

JSON can be formed of objects or arrays, and is formatted like a normal javascript, except that:

  1. strings must use double quotes
  2. keys must be in double quotes too
So this javasrcipt object:
{
  name: 'james',
  age: 38,
  isTutor: true
}
becomes this JSON:
{
  "name": "james",
  "age": 38,
  "isTutor": true
}

There is a global variable, JSON, available in your browser (window.JSON). The object is a helper object for dealing with JSON. If you type JSON into your console and hit return you'll be able to inspect it.

Objects or Arrays can be turned into JSON using JSON.stringify() and back again using JSON.parse(). On AJAX calls the response is usually converted for you on receipt of a response.

Making our first AJAX call

With natural javascript:

var xmlhttp = new XMLHttpRequest();

xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState === XMLHttpRequest.DONE ) {
       if (xmlhttp.status === 200) {
           document.getElementById("myDiv").innerHTML = xmlhttp.responseText;
       }
       else if (xmlhttp.status === 404) {
          alert('The resource was not found');
       }
       else {
           alert('Error: Call to server failed with code: ' + xmlhttp.status);
       }
    }
};

xmlhttp.open("GET", "ajax_info.txt", true);
xmlhttp.send();

More on readyState Here

We'll use jQuery because it's shorter/easier.

Try the following in your console:

$.ajax({
    method: 'GET', //optional. GET is the default if not provided
    context: document.body, //optional. Scopes the response to a part of your page
    url: '//api.github.com/users/jmsherry'
}).done(function(response){
    console.log(response);
}).fail(function(error){ //just to show you how to error catch
  console.error(error);
}).always(function(){ //this happens after EVERY ajax call
  console.info("ajax call made");
});

You can obviously replace my username with yours, assuming you have a github account, to see what you get back.

Once you get a response, lets build a template and inset your details into the page:

var source   = $("#profile-template").html();
var template = Handlebars.compile(source);

$.ajax({
  url: '//api.github.com/users/jmsherry'
}).done(function(response){
  //create HTML
  var html = template(response);

  //insert new HTML
  $('#ajax-content').html(html);
});

Demo

Current user is

Insert github profile here

Exercise:

Make your own ajax calls:

  1. Make an HTML partial and call and inject into page
  2. Make a .json file and call and template into page

Inject them here:

APIs

When you called GitHub you called a thing called an API (Application Program Interface). APIs are set up by people/organisations to allow others to interact with their business through servers

REST APIs

What is REST

REST stands for REspresentational State Transfer. REST is a way of keeping the state of an application in sync on the client and the server. For example, if a user removes an item from their shopping basket on the client we send an HTTP DELETE request to remove it from the basket on the server too.

HTTP verbs/methods used in REST

In development we have a thing called CRUD (Create, Read, Update & Delete). These are typical operations that you do with an app. REST has mapped those operations to HTTP methods so that everyone does things in a predictable manner, like so:

Operation HTTP VERB (Method) Purpose
Create POST To send new data to the server.
Read GET To retrieve an item/list of items from the server
Update PUT To update the stored details of a record. e.g. Maybe the price of an item changed??
Delete DELETE To indicate removal or deletion of a thing. (Server handles how)

Typical URL Format of a REST API

The URL Structure is important in REST. Using the standard structure well documents the API for users (meaning that they can guess where to call to acheive their aims).

An API has places you can call to, called routes. An example route might be: http://tesco.com/groceries/fruit/apples. This makes it easy to guess where you'd call to get oranges, right?!

HTTP Verb/Method Route Purpose
GET /posts Get all the posts
GET /posts/1 Get a post with an id of 1
GET /posts/1/comments Get the comments from a post with an id of 1
GET /comments?postId=1 Filter comments by id to get those related to a post with the id of 1 (Same as above but from a different angle.)
GET /posts?userId=1 Get all posts made by the user with the id of 1
POST /posts Add a new post to the database. The 'body' of this request would have an object in it, like: {userId: 4, createdAt: 234877892, content: "hello world!"}
PUT /posts/1 Also has a body which the server would use to update the post with an id of 1
DELETE /posts/1 Delete the post with an id of 1

Testing APIs with Postman

Sometimes, rather than doing it in your console, you'll want to test ajax calls using a client program, so that the information is easier to see and you can configure the call better. I tend to use Postman. We'll just have a brief look at that.

jsonplaceholder

One public 'dummy' API you can use to test is https://jsonplaceholder.typicode.com/. If you use Postman (or any ajax; or just your browser [in the case of GETs]) to make a request to it, then it will respond with data. Try making a get request to https://jsonplaceholder.typicode.com/photos, or making a PUT request to https://jsonplaceholder.typicode.com/users/1

Exercise:

Make calls to jsonplaceholder and template the responses.

Inject them here: