Implementing "Who's in Space" with Vue

Published January 14, 2020

Reading time: 4 minutes.

One of my favorite practice exercises from my book Exercises for Programmers is the “Who's In Space?” problem:

Did you know you can find out exactly who’s in space right now? The Open Notify API provides that information. Visit http://api.open-notify.org/astros.json to see not only how many people are currently in space but also their names and which spacecraft they’re on.

Create a program that pulls in this data and displays the information from this API in a tabular format.

I like this program for a few reasons. First, it's a little more challenging than “Hello World”. Second, it's a chance to pull data from a remote source that doesn't require authentication, so I get to practice consuming data without having to worry about getting an API key. Finally, it's just plain fun.

Let's implement a solution to this in Vue.js. To fetch the data, we'll use Axios, a promise-based library for making web requests.

This will be a single HTML page; we don't need Vue's CLI tooling for this. We'll link to the Vue and Axios libraries in the HTML page.

Let's get started.

First, explore the API. When you make a request to http://api.open-notify.org/astros.json you'll see results that look like this:

{
  "people": [
    {
      "name": "Christina Koch",
      "craft": "ISS"
    },
...
  ],
  "number": 6,
  "message": "success"
}

The API returns an object with three keys:

  1. people, containing the list of people in space
  2. number, containing the number of people in space
  3. message, containing a status message

Our app will take the people field and display it in an HTML table.

Create a new file called space.html and add an HTML template:

<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <title>Who's In Space</title>
  </head>
  <body>
    <div id="app">

    </div>
  </body>
</html>

The div with the ID of app is where you'll connect your Vue instance.

Within the div tags, add an HTML table for the results:

    <div id="app">
      <table>
        <tr>
          <th>Name</th>
          <th>Craft</th>
        </tr>
      </table>

After the table, add a link to the Vue library itself:

...
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
</body>

After that line, add a link to Axios:

  <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.1/axios.js"></script>

Now that the libraries are loaded, add a new script block and define a variable called url to hold the URL to the API:

  <script>
    const url = 'http://api.open-notify.org/astros.json';

  </script>

Then below the const url line, add the following code to define a new Vue instance:

    new Vue({
      el: '#app',
      data () {
        return { people: null }
      },
      created () {
        // Fetching data here
      }

    })

The el field connects, or “mounts” this Vue instance to the DOM element with the ID of app.

The data section returns an object with a field called people, which is set to null by default. The created section is where you'll fetch the data. created is one of Vue's lifecycle hooks. It fires before the Vue instance is actually connected to the DOM.

Within created, use Axios to make the request to the API and store the results in the people field of your Vue instance:

      created () {
       axios
          .get(url)
          .then(response => (this.people = response.data.people))
      }
    })

Axios gets the results and stores them in response.data. Remember that the API's response contains three keys: people, number, and message. Since you only need people, you pull down only that part of the results using dot notation.

Now that you have the data, display the results. Use Vue's v-for directive to iterate over the results, creating table rows that display the person and the craft:

    <div id="app">
      <table>
        <tr>
          <th>Name</th>
          <th>Craft</th>
        </tr>
        <!-- add this -->
        <tr v-for="person of people">
          <td>{{ person.name }}</td>
          <td>{{ person.craft }}</td>
        </tr>
        <!-- add this -->
      </table>
    </div>

The completed solution looks like this:

<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <title>Who's In Space</title>
  </head>
  <body>

    <div id="app">
      <table>
        <tr>
          <th>Name</th>
          <th>Craft</th>
        </tr>
        <tr v-for="person of people">
          <td>{{ person.name }}</td>
          <td>{{ person.craft }}</td>
        </tr>
      </table>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.1/axios.js"></script>

  <script>
    const url = 'http://api.open-notify.org/astros.json';

    new Vue({
      el: '#app',
      data () {
        return { people: null }
      },
      created () {
        axios
          .get(url)
          .then(response => (this.people = response.data.people))
      }
    })


  </script>
  </body>
</html>

When you view the page in your browser, you'll see the results:

The people in space right now

The app shows the people in space right now

This implementation doesn't have any styling, but the functionality is there. In the full book, there are some additional challenges for this exercise, as well as 56 other exercises you can tackle in any language you choose.

Now that you have this working in Vue, try implementing it with another language or framework.