Implementing "Who's in Space" with Vue
Tags: vue, javascript, tutorial, webdev
Published: 2020-01-14 13:32:55

---
title: Implementing "Who's in Space" with Vue
published: true
description: Solving the "Who's In Space" exercise from Exercises for Programmers in Vue.
tags: vue,javascript,tutorial,webdev
canonical_url: https://bphogan.com/2020/01/implementing-whos-in-space-with-vue/
---

One of my favorite practice exercises from my book [Exercises for Programmers](https://pragprog.com/titles/bhwb) 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](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](https://vuejs.org/).  To fetch the data, we'll use [Axios](https://github.com/axios/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:

```plain
{
  "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:

```html
<!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:

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


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

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

After that line, add a link to Axios:

```js
  <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:

```html
  <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:

```javascript
    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](https://vuejs.org/v2/guide/instance.html#Instance-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:

```javascript
      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:


```html
    <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:

```html
<!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](https://bphogan.com/2020/01/implementing-whos-in-space-with-vue/images/results.png)





This implementation doesn't have any styling, but the functionality is there. In the [full book](https://pragprog.com/titles/bhwb), 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.