Angular has its own built-in packages and libraries that developers can use to call external APIs and interact with web services. When we make calls to an external server, we want users to continue to be able to interact with the page. That is, we don’t want our page to freeze and block UI until the HTTP request returns from the external server. To achieve this effect, our HTTP requests are asynchronous.
Using HttpClient
Angular uses Observables to implement code in an asynchronous manner. Let’s have a look at how we can make calls to external APIs and retrieve data to be displayed in the app.
First of all, we need to inform the main AppModule that we are going to be using the HttpClient library. So add the following import to app.module.ts.
import { HttpClientModule } from '@angular/common/http';
And then add the HttpClientModule to the providers and import arrays.
... imports: [ ... HttpClientModule ... ], providers: [ HttpClientModule ], ...
That’s it. It is done. Now, we need to write the code in the component where we want to implement the HttpClient. Ideally, you would write the HttpClient related code inside a service, but for the sake of simplicity, let’s do everything within a component for now. For us, this component will be AppComponent.
Make sure that you restart the development server after making any changes to the app.module.ts file for the application to reflect changes.
Start by importing the HttpClient class from the same package, i.e. @angular/common/http.
import { HttpClient } from '@angular/common/http';
And then inject the service into the component by passing it as an argument to the constructor. The app.component.ts file should look like this at the moment.
Now we are ready to make an API call. To learn, we are going to use a free service called https://reqres.in. This service allows testing the application by allowing the application to make free GET and POST requests and returns some fake data. For now, we will be using the /api/users' endpoint to get a list of fake users.
https://reqres.in/api/users?per_page=10
The above URL is the one that we will be using to retrieve a list of 10 fake users where each user has information including id, email, first_name, last_name, and an avatar.
We will now create a new method called getUsers() and write the code to make GET request using the HttpClient library inside this function.
The HttpClient library offers methods that we can use to make different kinds of HTTP to a server. Here is a screenshot that clearly shows all the available methods it offers.
Let’s go ahead and use the get() method and pass the API URL to the get() method as the only argument. The method returns an Observable object that we can subscribe to using the subscribe() method. The subscribe method takes two methods as arguments, the first one being the success callback and the second one being the error callback.
Let’s log the retrieved response to the console and see what we get by running the application. Make sure that you call the this.getUsers() from within the constructor otherwise nothing will work.
Here is a snapshot of the response that we get to see in the browser’s console.
The response is a JSON object and it contains properties like a page, per_page, total, etc and a property called data which is an array of JSON objects. Each object in the data object contains information about one of the users.
Let’s extract the data object and store it inside an array in the TS class which we can then use in the template to render the list of the users.
Now that we have a response.data in this. users array, let’s use it in the HTML to render the list of users.
Save the file and let’s have a look at the output in the browser.
Looks great, right!It is easy to retrieve data from an external API and display it in the app with Angular.Page Break
Angular Router
So far we have been working with components, services, and pipes. But all this while we have been working within a component. A component might be placed inside another component and so on but there was never navigation. Therefore at any point in time, the user will be presented with a set of components scattered across the screen, and we need to provide a better navigational experience and a logical way to change the application's state intuitively.
A web application is incomplete without navigation. Navigation is key to presenting only useful components to the user at any given time. As the user requests or uses the app, the presented components are changed and the user is presented with different sets of components.
This is made possible with the help of routing in Angular. Angular provides us with amazing functionality via the Angular Router that we will learn to use next. Having a router in the application means that we want to navigate between different sets of components or different topics in the application. In SPAs (Single page applications), navigating from one topic to another just changes the URL a little bit but it never reloads the page in the browser. So the application feels very fast and performant.
Setting up an Angular Router
To set up an Angular Router, we need to set up a few things.
So we start at the top.
Step 1: Navigate to index.html in the project’s root directory and if not present, add the following code the <head> section of the HTML document.
<base href="/">
For newer projects, this would already be there when you create a new Angular project. So if it is already there, feel free to move on to the next step.
Step 2: If you chose Angular routing in the project when you created a new project with the Angular CLI, you should already have a file called angular-routing.module.ts inside the app directory. The file looks something like this.
The file basically creates another module within the app called AppRoutingModule. It imports the RouterModule which is provided by the @angular/routing package. It also imports a type called Routes which we use to create our own routes array. If you look in your app.module.ts file, the AppRoutingModule should be imported and added to the import array. Here is a screenshot showing how the app.module.ts looks.
Step 3: Now that we have everything in place, it is time to define the routes inside the routes array and for this need to create a few components in the application. So very quickly, we will create two new components called AComponent and BComponent and then we will set up routes for these components. While you create the components, add a little bit of HTML to each one so that you can identify the component when it is later displayed on the page. So here is how the a.component.html and b.component.html look like for me.
Once you have created the two components, in the app-routing.module.ts file, the routes array definition should look something like this.
Every object in the array is a Route object which contains a path and a component property. The path and component properties specify what component should be displayed when the corresponding path is found in the browser’s address bar. So, http://localhost:4200/a would display AComponent and http://localhost:4200/b would display B Component. The last route is a fallback route that will be displayed if the path in the browser does not match with the path of any of the Routes defined. Here, in that case, Component A will be displayed.
Step 4: Once we have come this far, it's time to define a viewport where the routed content should be rendered. At this point, we involve the router-outlet element. It is an element that tells the router that this is where it should render the content.
Inside the app.component.html, place the <router-outlet> element and remove everything else.
That’s all. Routing is all setup. We do not have a way to perform navigation as of now because we have not created any buttons or links to navigate but for now, we can test using the browser’s address bar. We will change the address manually. Serve the app using ng serve and you should be presented with the Acomponent.
There we go. Let’s change the URL to localhost:4200/a and see what we get.
We still get the AComponent and that is what is expected. Let’s change the URL to localhost:4200/b and this time we should see some changes.
Perfect! And if you add anything except “a” and “b” in the URL, you will still fall back to the AComponent. Let’s try localhost:4200/xyz.
So we understand how Angular Routing works now. But how do we add links so that the users can navigate and how to write code to navigate here and there within the app? Let’s look at the answers to all these questions.
RouterLink and RouterLinkActive
In this section, we are going to learn how we can set up links in HTML to navigate the user within the application between different components. Let’s create a simple button bar to create links for the user to be able to navigate. Add the following code to the app.component.html file.
Notice the router link directive. It is used to tell Angular what URL to navigate to when the user clicks on this button. Let’s save everything and test this out in the browser.
Works as expected.
We use the router link instead of the regular href because href would make the app send a GET request to the server and the app will reload; while the router link ensures that the app does not do that and instead loads the component locally.
Now, let’s make both the buttons the same color i.e. class="btn btn-primary" and apply the routerLinkActive directive. Set the value to active which is the name of the CSS class that is applied automatically when the corresponding route is activated.
Let’s test it out again. This time you will be able to identify, by looking at the colors of the button, which particular route is the active one.
Awesome. Moving on, let’s have a look at how we can navigate programmatically and pass parameters from one component to another as we navigate.
Router and ActivatedRoute
In this section, we will redefine the two components - AComponent and BComponent. Instead of navigating using the Buttons in the AppComponent, we will add a button within AComponent which will navigate the user to BComponent. Also, this time, we will not be using the routerLink directive. Instead, we will be writing the navigation logic within the TypeScript class for AComponent.
So let’s get rid of everything else except the <router-outlet></router-outlet> in the app.component.html file.
Next, add the following HTML code to a.component.html.
This will add an HTML input and a button to the components UI. We will use the input to receive some input from the user and then send it to BComponent when we navigate on the click of the button.
As you can see in the HTML, the HTML input value is bound to a property called name in the TypeScript class using the NgModel directive and the click event of the button is bound to a method called onSubmit(). Let’s create the property and method in the class.
Next, import the Router class from @angular/router package and inject it into the component by passing it as an argument to the constructor. Finally, we use the navigate method on the Router service to navigate the user to BComponent.
The navigate method takes an array of strings that will eventually form up the URL to which the user will be navigated. In this case '/b' is enough.
Feel free to test this out. Whether you fill out the input field or not, clicking on the button will navigate you to BComponent.
Now comes the last part. We want to send the value of the name (the name entered by the user in the input field) as we navigate and then display that value in BComponent.
To do that, first of all, we will have to modify the entry for the path /b in the app-routing.module.ts file. We need to tell Angular that this route should expect a parameter. Add the /: name to the path string which indicates that we will be sending a parameter with the name name.
{ path: "b/:name", component: BComponent } Change the onSubmit function definition like this. onSubmit() { this.router.navigate(['/b/' + this.name]); }
If you test it out, fill out the name field and click the button, you will notice that the URL changes to something like http://localhost:4200/b/<name>.
Lastly, we will be writing the code in the constructor of BComponent to retrieve the value of the name parameter. For this, we need to use a service called ActivatedRoute. Change the code in b.component.ts and b.component.html to look like the following.
We use the ActivatedRoute service’s method to get the value of the parameter by the name and assign it to the class property this.name. Finally, we use interpolation to display it in BComponent.
Here is the final result.
That’s all about routing in Angular.
Build an Angular App
So now that you know a lot about building and serving Angular apps locally on your system using the development server that Angular CLI spins up, it is time to build your app for production and make it ready to be published online.
To build the application, we again use the Angular CLI. All we have to do is execute a simple command and the CLI takes care of the rest. The command is
ng build
The above command builds the app. It transpires all the TypeScript code to the corresponding code and also optimizes it. After the command finishes, you can find the final build files in the dist folder in your project folder. You can directly upload the files from the dist folder to your server’s webroot and your website will start working.
You should also use the --prod=true flag to ensure that the CLI applies all production settings while building the app. It also ensures that the build size is less and Angular CLI ensures that the build files are minified and uglified as well so it becomes harder for hackers to reverse-engineer the code. The command becomes
ng build --prod=true
The build command also takes a number of flags but --prod is the most important and mandatory one when building for production. You can read about all other flags here (https://angular.io/cli/build#options).
That’s all about building Angular apps using the Angular CLI.
great learning blog!
great blog!
Build various types of web applications,command-line application,etc....
JavaScript is a dynamic computer programming language for the web. Jav...
Leave a Reply
Your email address will not be published. Required fields are marked *