You can view the source code for this project by following this link: GitHub
Demo
Buy milk
Buy eggs
Buy bread
Try to click into the add button many times and see that task is added only once.
Intro
You have a button on a website.
When a user click this button you want to send a HTTP request to the server.
Even for this simple task there is a lot of cases to handle:
show loading component when request is in progress
handle HTTP error response
block sending a next request until the previous one is not ended
As you can see there is a lot of boilerplate code.
You have to repeat this code for every button which calls a asynchronous action.
Moving logic to directive
We can move this logic to a directive and reuse it in every place where we need it.
Now the directive calls subscribe method and manage the subscription.
Additionally, it uses takeUntilDestroyed operator to automatically unsubscribe when the component is destroyed.
Now we can use this directive in our component.
To do this we need to refactor our component a little bit.
We can remove saveInProgress signal and replace it with appAsyncAction directive.
As you can see we have removed a lot of boilerplate code from our component.
Problems with save() method
There is one problem with this approach.
We call save() method in the template.
That means that every time the template is rendered the save() method is called.
To fix we cannot use save() method directly.
We need to call it and store the result in a variable.
Problem with dynamic data
There is another problem with this approach.
If the data is dynamic we need to call getSaveAction() method every time the data changes.
Right now we call getSaveAction() method only once when the component is created.
That means when we subscribe to save$ observable it will always send the same data.
To fix this problem we need to call getSaveAction() lazy.
That means only call the getSaveAction() method when the save$ observable is subscribed.
We can do this using defer operator.
defer allows you to create an Observable only when the Observer subscribes.
See defer operator in action:
Problem with template variables
There is one more problem with this approach.
The getSaveAction() method is called in the context of the component.
If you want to use template variables in the getSaveAction() method you cannot do this.
As you can see we cannot use todo variable with save$ variable.
To fix this problem we need to extends our AsyncActionDirective directive with additional input.
Now we can update our component.
Do you like the content?
Your support helps me continue my work. Please consider making a donation.
Donations are accepted through PayPal or Stripe. You do not need a account to donate. All major credit cards are
accepted.