Welcome to the follow-up article on enhancing Pokefetch!
In this blog, we will dive into error handling in Angular and implement it in our project. Handling errors is crucial for a smooth user experience, especially with external APIs like PokeAPI. We will create an ErrorMessage component to handle error messages and display them in an alert modal. By passing the error status from the PokemonSearchcomponent to the ErrorMessage component, we can effectively communicate any API errors to the user.
This tutorial will explore the steps to implement error handling, ensuring our Pokefetch project becomes even more robust and user-friendly.
Let’s get started!
Creating the ErrorMessage Component
To handle error messages in Pokefetch, we will create an ErrorMessage component. This component will display the error message in an alert modal.
Start by generating the ErrorMessage component using the Angular CLI:
ng generate component components/error-message
Next, open the error-message.component.ts
file and update it with the following code:
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'app-error-message',
templateUrl: './error-message.component.html'
})
export class ErrorMessageComponent implements OnInit {
@Input() isAPICallErrored: boolean;
constructor() { }
ngOnInit(): void {
}
hideDiv() {
this.isAPICallErrored = false;
}
}
This code defines an isAPICallErrored
input property using the @Input
decorator. This property will determine whether an API call has resulted in an error. We also provide a hideDiv
method that sets isAPICallErrored
to false
when invoked.
The hideDiv()
method in the ErrorMessage component allows the user to dismiss the error alert by setting the isAPICallErrored
property to false
. By clicking the close button in the error alert, the hideDiv()
method is triggered, hiding the error message and allowing the user to proceed with their search.
Now let's create the HTML template for the ErrorMessage component. Open the error-message.component.html
file and add the following code:
<div *ngIf="isAPICallErrored">
<div
class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
role="alert"
>
<strong class="font-bold">Holy smokes! </strong>
<span class="block sm:inline"
>Seems you have entered invalid data or the API is down. Please
retry!</span
>
<span class="absolute top-0 bottom-0 right-0 px-4 py-3" (click)="hideDiv()">
<svg
class="fill-current h-6 w-6 text-red-500"
role="button"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
>
<title>Close</title>
<path
d="M14.348 14.849a1.2 1.2 0 0 1-1.697 0L10 11.819l-2.651 3.029a1.2 1.2 0 1 1-1.697-1.697l2.758-3.15-2.759-3.152a1.2 1.2 0 1 1 1.697-1.697L10 8.183l2.651-3.031a1.2 1.2 0 1 1 1.697 1.697l-2.758 3.152 2.758 3.15a1.2 1.2 0 0 1 0 1.698z"
/>
</svg>
</span>
</div>
</div>
In this HTML template, we use Angular’s structural directive *ngIf
to display the error message conditionally. When isAPICallErrored
is true
, the error alert modal is shown. The user will see the error message and can click the close button to hide the error alert.
Please note that at this point, the isAPICallErrored
property has not been passed from the PokemonSearch component to the ErrorMessage component. We will cover this in the next section.
Passing Error Status from PokemonSearch to ErrorMessage Component
To pass the error status from the PokemonSearch component to the ErrorMessage component, you can make the following modifications to the code:
- Declare a boolean property named
isAPICallErrored
in the PokemonSearch component and initialize it tofalse
:
isAPICallErrored: boolean = false;
- Inside the
subscribe()
method of thegetPokemonType()
function, setthis.isAPICallErrored
tofalse
when the API call is successful and the type is retrieved:
this.pokemonService.getPokemonType(this.searchTerm).subscribe(
type => {
this.pokemonType = type;
this.isAPICallErrored = false;
},
error => console.log(error)
);
- Add parameter
error
to the error callback function inside thesubscribe()
method:
error => {
if (error) {
this.isAPICallErrored = true;
}
}
The isAPICallErrored
property will correctly reflect the error status by implementing these changes. You can then pass this property to the ErrorMessage component to display the error message when an API error occurs.
In the PokemonSearch component, when the API call is successful and the type is retrieved, setting isAPICallErrored
to false
ensures that any previous error state is cleared, allowing for accurate error handling in subsequent API calls.
The final version of the PokemonSearch component code with the implementation of error handling will look as follows:
import { Component, OnInit } from '@angular/core';
import { PokemonService } from '../../service/pokemon.service';
@Component({
selector: 'app-pokemon-search',
templateUrl: './pokemon-search.component.html'
})
export class PokemonSearchComponent implements OnInit {
pokemonType: string;
isAPICallErrored: boolean;
constructor(private pokemonService: PokemonService) { }
ngOnInit(): void {
}
searchTerm: string;
search() {
this.pokemonService.getPokemonType(this.searchTerm).subscribe(
type => {
this.pokemonType = type;
this.isAPICallErrored = false;
},
error => {
if(error){
this.isAPICallErrored = true;
console.log(this.isAPICallErrored);
}
}
);
}
}
This component version includes the isAPICallErrored
property, which is set to true
when an error occurs during the API call. This property allows for proper error handling and can be used to display the error message using the ErrorMessage component.
To add the ErrorMessage component and pass the isAPICallErrored
variable, you can modify the pokemon-search.component.html
file as follows:
<app-error-message [isAPICallErrored]="isAPICallErrored"></app-error-message>
<div class="flex justify-center mt-20">
<form class="flex items-center">
<input
type="text"
placeholder="Search Pokemon"
[(ngModel)]="searchTerm"
name="searchTerm"
class="py-2 px-10 rounded-l-md focus:outline-none"
/>
<button
type="submit"
(click)="search()"
class="bg-blue-500 hover:bg-blue-700 text-white py-2 px-4 rounded-r-md"
>
Search
</button>
</form>
</div>
<div class="flex justify-center mt-10">
<div
*ngIf="pokemonType && pokemonType.length > 0"
class="max-w-sm rounded overflow-hidden shadow-lg"
>
<div class="flex items-center flex-col px-6 py-4 bg-green-300">
<div class="font-bold text-xl mb-2">Type</div>
<p class="text-gray-700 text-base">
{{ pokemonType }}
</p>
</div>
</div>
</div>
In this updated code, the <app-error-message>
component is added at the beginning of the template. The isAPICallErrored
property is bound to the isAPICallErrored
input of the ErrorMessage component, allowing it to receive the value and handle the display of the error message accordingly.
Point to Note
It is important to mention that due to PokeAPI's limitations, we cannot provide specific error messages for spelling errors or invalid search terms. The API does not return detailed responses for such scenarios. Therefore, the error message displayed in the application is a generic message indicating that the entered data is invalid or the API is down. While we have implemented error handling to handle these situations gracefully, it is recommended to double-check the spelling and accuracy of the search term when using the Pokefetch application.
Demo of Error Message in Action
This is how the error messages will look on the application after implementing the above codes.
You can try it out live at Pokefetch.
Conclusion
In conclusion, we have successfully implemented error handling in the Pokefetch application, enhancing its functionality and user experience. Adding the error message component allows us to display informative messages when API calls fail or return errors. This ensures that users are informed about issues and can take appropriate actions.
However, there is always room for improvement. In the following steps, we can further enhance error handling by implementing additional techniques such as logging errors, providing more detailed error messages, and implementing error tracking and reporting. We can create a more robust and user-friendly application by continuously refining and enhancing.
Lastly, Your support keeps me going, and I give my 100 percent to these blogs! If you've found value, consider fueling the blog with a coffee ☕️ donation at the below link.
Thank you! 🙏
Top comments (0)