HTTP Calls

ionic-4-crash-course-day-3
Welcome to the 3. lesson of the Ionic Crash Course!

Today we will get into details on HTTP requests and how to use services to structure our app.

We will make use of the Star Wars API, a public and free available API with JSON results which is exactly what we need right now!

1. Basic HTTP Calls

First of all we have to tell our app to include another Angular module to make HTTP requests. This is already installed, we simply need to load and add it insider our app/app.module.ts like this:

Now we are ready to make HTTP calls to anywhere we want!

If we want to use external resources like this, the operation is asynchronous.

Whatever you are trying to call takes time, and this happens in the background of our app and at some point returns data.

With Angular we can use Promises and Observables. If you have used AngularJS you might already know about Promises, which are called and at some point return either a result or an error.

Observables are a bit newer and allow more control, for example you can cancel an observable or receive multiple return values. You can imagine it as more like a stream of events where a promise was only one click.

So the request we make to the Swapi returns us an observable which we can assign to a local variable. We use the standard Angular Http service to make a classic GET request.

A classic promise was handled with then(), which was triggered once when the result came in.

As we now have an observable, we need to subscribe() to the stream of data that might come back! Inside that block we finally get the result of our call.

Now open your pages/films/film.page.ts and change it to:

If you now open your app, it takes a short time after the start (remember: async!) and inside your debugging area you should see a log message where we can find and inspect different objects of the call we made.

ionic-json-result

NOTE: It can happen that you get a message like this inside your browser:

Failed to load http://swapi.co/api/films: Redirect from ‘http://swapi.co/api/films’ to ‘https://swapi.co/api/films’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost:8100’ is therefore not allowed access.

This is an CORS issue that you will get inside the browser (but not later inside a real app!). You can simply add this Chrome extension and enable it, then the requests should also work inside your browser!

If you have come to this point you are already pretty close to displaying them, so let’s not only log but display them inside our view!

2. Displaying Asynchronous Data

With Angular we can easily use observables directly from our view. We don’t have to wait for the result and assign it then, but we can simply set the variable to the result of our HTTP call and handle the rest inside the view!

Therefore change the pages/films/films.page.ts back to a more simplified version:

We are now doing the same routing but pass the id of a film episode to the next page so we can then retrieve the data for that film from the API!

Inside the next code block we got a few new elements, especially:

  • *ngFor: A syntax to iterate over and array and create multiple elements of the same type
  • | async: Called a “Pipe”, and tells Angular to observe this variable as it will change later
  • ? : Operator that tells Angular that the variable might be null, please don’t crash

The film object we create with each iteration of our loop is directly passed to the click event and will make its way to the next page.

Inside the Ionic list we will create multiple items by using this loop, a very very common pattern you will see in Angular apps!

In every loop we simply add the title of the film to the button, so in the end we will have a list of buttons to open the detail page for each.

Go ahead and change your pages/films/films.page.html to:

The last missing part now is to change the details page which is not really displaying any of our data.

We are already passing data through with our routing so now we only grab the id and make another call to retrieve the appropriate API information. Therefore, change the pages/film-details/film-details.page.ts to:

Just like before we are extracting the value to a local variable. Now we can use that variable inside our view to set the title and display a cool little card with the opening of the selected Star Wars movie.

Open your pages/film-details/film-details.page.html and change the view to read the values from our variable:

We also added a new Angular expression with *ngIf which is a basic check and if true, the object is added to our DOM and if false, it’s not displayed. In our case we only want to display the Ionic card with the text if we have filled our film value before.

You can now get a list of films and display for each film the data, only with a few lines of code!

ionic-4-http-details

I’m always amazed when using a REST API and the data just comes in after implementing it only once for the general case. Perhaps you’re like me.

Anyway, we can improve our app structure a bit which is kind of a best practice for Ionic apps.

3. Using Services

A service is an Angular component that can be injected (remember dependency injection!) into other pages which allows us to call some functions.

A service has no view, it’s only returning data to us. And that’s exactly what we need.

It’s a good idea to keep your HTTP calls separate from your view and class, because it can be maintained more easily and it’s not distributed across your entire project!



Creating a Service

We can again make use of the Ionic CLI and call the generator to create a new service for us. Simply call this from your projects root:

Our service has only a very tiny job: Return data from the Swapi!

It’s more or less the same code like we had in our page before, so go ahead and change your services/api.service.ts to:

Our service has now one function getFilms() which we can call from outside to get all films, and another to get one specific film by it’s id so let’s do this!

Using the Service

Our FilmsPage is the first page to make use of our new service.

Just like with any other stuff we used before, we need to import the file and inject it through our constructor.

By doing this, we can use it directly and call it’s functions, which will again just return an observable like before.

Open your pages/films/films.page.ts and change it to:

Very easy, isn’t it?

Let’s put the same changes into our pages/film-details/film-details.page.ts so we have our service as the only source of data:

Our app still works just like before, but we have now separated our business logic from the view to a service.

So whenever you think about the business logic of your app, try to keep them in a separate service where you can bundle it.

Then the force will always be with you.

4. Next Steps

Congratulations on finishing the 3. lesson!
You are now already pretty skilled and able to perform HTTP requests, good job.

As a little homework for today you can also implement the following changes to get a better feeling for the CLI, services and routing:

  • Add more functions to the service to load people and planets
  • Implement the PeoplesPage and PlanetsPage with the data you get from our API service
  • Generate 2 more pages for peopleDetails and planetDetails like we did for our film and add the routing

After doing those steps you have 3 working tabs with lists and detailed data pages!

I’m sure you can do this. If you have any questions, feel free to hit me up on @schlimmson.