Srt Neil

Feb 18, 2021

6 min read

Build a simple crime-info web app using JavaScript

JavaScript beginner (like me)?

Looking for something quick and simple to build that touches on a few important concepts?

Hopefully this will tickle your fancy.

I’ll run through how to build a very simple web app using JavaScript that consumes data from the UK police API, to display crimes recorded at a specified location.

Ok, so police records might be kind of a heavy topic, but the API in question is super easy to use and doesn’t require an API key — it would be a crime not to play around with it.

Before we start, a disclaimer, or, to really milk the crime theme, a confession: this is just a bit of basic fun and, as always, there are probably better ways to build what I cover here. If you have any suggestions, please do shout out in the comments.

With that out of the way, let’s do this.

What we’ll build

We’ll build a web app that allows a user to input a UK location, in the form of a latitude and longitude, and to display in the browser a few details of the crimes recorded at that location.

We’ll implement this using the crimes-at-location method from the UK police API.

The full code is provided at the very end of this article.

The web app

I’ll assume you’re already set up and have a bit of familiarity with using a code editor (I’m using VS Code); however, if this is all new to you, this article may help.

In a new directory, make three files: index.html, app.js and main.css.

We’ll mostly be working in app.js (and we’ll do very little in CSS), but first, let’s start with our HTML file: Add some boilerplate, including and tags with relative paths to the main.css and app.js files, respectively.

We’re going to request data from the police API based on coordinates of latitude and longitude. Let’s take a quick look at the API docs to help us plan our approach in getting data from it: Here we can see that the API endpoint has the following format:

Just to see what the data returned from the API looks like, let’s make a request to the API using some actual coordinates. For this, you could use an API testing tool, such as Insomnia or Postman; However, for our simple example, I’ll just paste the following into the browser search bar:

This uses the latitude () and longitude () for Covent Garden, London, and gets back an array of objects containing crime data:

For our web app, we want to allow a user to specify their own coordinates for latitude and longitude, and submit a request to the API using these coordinates as request parameters. So, back in the html, inside the element, let’s include a element with s for coordinates, as well as a submit to kick-off the request to the API. At this stage we’ll also add a element, where data from the API will ultimately be displayed. We’ll include an header element too, just to give the app some heading text. Here’s the snippet of the html to add inside of the :

The JavaScript bit

Now in app.js, we’ll start by adding some code to get access to our ’s submit button, as well as its fields. While we’re at it, let’s also get access to our with the class of , we’ll need this later:

Next, add an event listener on the submit button that will execute a callback function when the button is clicked.

submitButton.addEventListener('click', handleSubmit)

And let’s define the function :

Above, we first use to prevent the page re-loading when the submit button is clicked. Then, we incorporate the values of latitude and longitude in a string, , representing the API’s endpoint. Finally, we call another function, that takes as an argument.

is where the sausage really gets made — this is where we’ll make the request to the API and determine what to do with the response that comes back. Let’s start defining this function as follows:

Above, we use to start our request to get data from the . However, we don’t know how long this process will take, and we want the browser to continue working while we’re waiting for the data to be received. To achieve this, we use syntax. Here’s a good article covering the syntax, along with the use of for extracting the JSON object from a fetch response.

To summarise, on line 3 of the snippet above, we await the from . Then, using the method, we extract the JSON object from and assign it to the variable . In a moment, we’ll add in a call to another function, to display the data in the browser window. But for now, we just log the result, using .

If we’re using valid latitude and longitude coordinates, we should get a successful response from the API. But what if, for whatever reason, the API returns an error rather that the data we had hoped for? To add some simple error handling, we use . This way, if an error occurs in the block, the block runs (for now, this just results in a ).

Here’s the code so far:

And here’s what it looks like using the console in Chrome DevTools, when we submit our form with valid latitude and longitude coordinates:

Great. We have data being logged to the console. Now try with some invalid coordinates (e.g., 1234, 5678) and see the error message that gets logged.

Instead of logging all of the data to the console, we want to display selected parts of it in the browser window. To do this, replace the in with a call to a new function , taking as an argument.

We’ll define as follows:

In the above function, we over and for each in the array, we return a template literal that incorporates selected parts of the crime data, accessed using dot notation; for example , and . The result is stored in , which is an array of strings. Note also that each string resembles html, as we’ve included and tags in the template literal.

Finally on line 10, we the elements of together, and use to inject the resulting string as HTML into .

We’re almost done. Let’s just make a few small additions to account for the following possibilities:

  1. We get a successful response from the API (no errors), but no crime records exist at the location specified.
  2. The API returns an error. For example, if the user inputs invalid coordinates.
  3. The API takes a long time to return data, leaving the user wondering what’s going on.

1. Successful response, but no crimes recorded at the location

If no crimes have been recorded at the location, will be an empty array. Let’s account for this by including the following within our function definition, immediately after we have defined .

if (allCrimes.length === 0){  crimesContainer.innerHTML = 'No crimes found'  return}

2. The API returns an error.

Let’s display a simple message in the browser when an error occurs. Define a new function:

And add a call to this function in the block of (replacing ). In this case the displayed won’t be particularly useful, but it at least lets the user know that there was a problem.

3. The API takes time to return data

We don’t know how long, following the user clicking the submit button, it might be before data is returned from the API and displayed on screen. We can let the user know that they should await the response by including a simple message in while awaiting the response from the API. At the top of the function, on the line above , include a call to a new function , and then define that function as:

Finally, add a tiny bit of CSS into your main.css file, just to separate out the information on screen:

.crime-container{border: 1px solid black;margin: 5px;padding: 5px;}

And that’s it! We now have a simple web app that displays information on crimes at a user-specified location. The app also does some basic error handling and displays a simple loading message.

Here’s the final code in CodePen: