Almost every Angular developer knows this scenario. You've got your Observable all set up for data retrieval from your API via Angular's HttpClient. Now, you're ready to display this data in your template, but here comes the challenging part: what about the states during the data loading process? If the data's loading, you need a spinner; if there's an error, show an error message; and finally, when the data is loaded, you display the data. It seems like a simple enough requirement, but it's also one of the most repetitive parts of writing an Angular application. Today, we will look at a new way to handle this problem.
The Traditional Approach
The usual approach we find in most Angular projects involves using the *ngIf
directive. A typical scenario might look like this:
<div *ngIf="data$ | async as data; else loading"> {{ data }} </div>
<ng-template #loading>loading…</ng-template>
And then, we would sprinkle in another *ngIf
statement for errors. This approach isn't complicated, but it’s a lot of repetition and the possibility of errors creeping in is high. Besides, the multiple *ngIf
statements can clutter your template and require extra testing effort.
A More Declarative Approach
Instead of dealing with the hassle of multiple *ngIf
statements, we can adopt a more declarative approach. Just specify what needs to be displayed when the data is loaded and optionally specify what to display when the data is loading and when an error occurs.
Leveraging ngx-observe
ngx-observe is a brilliant library that allows for a more declarative way of dealing with loading states in Angular. It provides a structural directive that wraps around the logic of managing subscriptions and choosing the correct templates based on the loading state.
Here is how it works:
<div *ngxObserve="data$ as data; loading: myLoadingTemplate; error: myErrorTemplate"> {{ data }} </div>
<ng-template #myLoadingTemplate>loading…</ng-template>
<ng-template #myErrorTemplate let-error>{{error.message}}</ng-template>
As you can see, the ngx-observe directive allows you to focus on what matters - the templates for the different loading states.
Check out Nils Mehlhorn's excellent article here for a deeper dive into how ngx-observe works.
Introducing ngx-load-with
Inspired by ngx-observe, I decided to create a library called ngx-load-with. It provides similar functionality but with some extra features that allow for more flexibility. These include easy reloading and loading based on other variables like route parameters or search box input.
While ngx-load-with still allows you to leverage the full power of RxJS, its aim is to streamline your code and reduce the necessity of using complex RxJS operations for common use cases.
To give it a try, please check out the documentation here.
Conclusion
Repetition and boilerplate code can often lead to errors and decrease the maintainability of your codebase. By adopting a more declarative approach to handle loading states in Angular, we can write cleaner, more reliable code. Both ngx-observe and ngx-load-with offer a more elegant way to handle loading states, allowing you to focus on the essence of your application - delivering an excellent user experience.
Top comments (4)
Looks fantastic !! Thanks for charing
Thank you for your kind words! :-) It's wonderful to hear that you found the post useful. I put a lot of thought into it, so your feedback is very much appreciated.
I'm curious, have you tried using any of the structural directives I mentioned in the article? If you're up for it, I'd love if you could try my ngx-load-with library and share your thoughts. Your feedback could really help me refine it further for the Angular community.
Let me know if you decide to give it a go!
hey, we've not used it yet but we have some projects made with angular with lots of ngIf and we will give a try to those components in order to improve code
Awesome! Good luck and let me know if you run into any issues :-)