Angular self-saving dropdowns — yet another directive
“It is not enough for code to work” — Robert C. Martin
This story was originally published at inDepthDev
The angular directive is a powerful pattern provided by the framework which can be used to add additional behaviors to the elements. We will create a custom Angular directive in this article to enable self-saving (autosaving) for dropdown elements.
What is a self-saving dropdown anyways?
Consider this simple scenario in an example application where you have a dropdown to determine the sexual age group of a person. The natural and efficient implementation of this case is to use a dropdown with options. It is typical to use a form with a dropdown field and a submit button. But what if this dropdown is not part of a larger HTML form? What if this is a single select item on the page without a save button? You might not want the user to click a button to initiate the save in some cases as it can cause friction.
We can use a self-saving dropdown that syncs the state with the backend database on dropdown change events. You can find this pattern commonly in react applications with the data fetcher approach where the component is responsible for fetching its required data itself.
Great! Now, how do we communicate to the user that this change triggered a save? How do we let users know in case of an error?
It is obvious that we need an elegant solution to provide visual feedback to the user of in-progress, success, and failure events. This is where you might want to implement self-saving behavior.
Let’s get to it
Take a peek into the final results on how it works before we start.
That looks cool, doesn’t it?
Let’s now outline the plan
- The directive should take an input that refers to the HTTP call being made to the backend.
- When the host element triggers the ‘change` event, we need the listener to run.
- Need to show the loader before the subscription
- Need to remove the loader, add green tick icon on a successful call
- Need to remove the tick mark after one second
- On failure, need to show the error icon next to the select field
In the diagram,
Flow chart — self saving dropdowns
Let’s start by creating an Angular directive using the Angular CLI.
ng generate directive self-save
We will have only one input to this directive, ie
@Input(‘observableFn’)
observableFn!: () => Observable<any>;
`ObservableFn` will have the reference to the HTTP request that has to be made to save this particular data. We will be passing this information down from the parent where this directive is getting used.
Let’s now bring in ElementRef, Renderer2, and Document
constructor(
private elRef: ElementRef,
private renderer: Renderer2,
@Inject(DOCUMENT) private document: Document
) {}
We will be using these dependencies to
- ElementRef — Refer to the host element
- Renderer2 — To Attach the error text element in case of error
- Document- reference to the document
We need to listen to the change event on the host element to know when the dropdown value changes
@HostListener(‘change’)
onChange() {
// Do all craziness
}
Let’s start implementing the self-saving behavior now,
We are making use of the elementRef
to grab the native host element(select element) as we need to manipulate this as we go. Next, we are subscribing to the observable that is already passed as the input by calling the input function. There are two helper methods here to which we are passing the select element. Let us now see how they are implemented.
This code follows the initial flowchart that we created. ie, on change of the dropdown value,
- Adds a loader to the element to indicate save in-progress
- Gets the HTTP observable and subscribes
On success
- Removes the loader background
- Add success tick icon
- Remove the tick icon after 1 second
And on failure,
- Create a dummy div element to hold the error text
- Populated the
innerText
as the error message received from the server - Use Renderer to append this child element to the parent node so that the error message is not displayed below the dropdown
Let us now implement these helper methods that we used above,
To add a loader to the dropdown
The same can be followed to add the success indicator as well,
Now to implement the addBackground()
method,
We can simply set the element background to `none` to remove the background
Now to use this directive on any select element,
Let us also create the post()
method which returns a function that returns the HTTP observable.
You can play around with the stackblitz project here.
Conclusion
Directives are very handy when it comes to a repeated pattern that we need to apply to multiple elements in our application. They can be used to make reusable patterns across the application and make the developer’s life easier by keeping the application cleaner!