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:
-
people
, containing the list of people in space -
number
, containing the number of people in space -
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:
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.
Top comments (2)
Fun example. I'm not really a js "person" but I've wanted to try vue.js and who doesn't like spaceships? However, I don't get the data rendering in my browser. When I turn on devtools I see some errors about axios not being defined. I typed up the example by hand once and tried copy/pasting your example. Neither worked. :( Any ideas?
I wonder if you just happened to hit it on a day when there were some issues with Axios from the CDN, which is always a problem. I just copied the full example at the end of the tutorial to a new file and it worked without any issues.