In this post, we are going to look at tips you can use to make your components more reusable. Reusing components allows developers to avoid code duplication, which can introduce errors and bugs and are also hard to troubleshoot. Take for instance a shopping site, the product display component, whether the product is electronic or beverage, can be displayed using the same component.
So, it would make sense to make sure that this component can be re-used in multiple situations such as the homepage recommendation, product category listing, search listing and cart. Making it more aware of where it is being use and altering the behavior accordingly.
In such a case, any bug or error detected within the product itself becomes very easy to fix. This is because it’s a single component, rather than multiple components. In case of multiple components, each would have to be updated. For a small project, that might not be a problem but as the project grows, it becomes a nightmare to manage.
Having a single large component has several disadvantages, such as: It makes code hard to read, code can become very messy and they are not very re-usable. One way to know that your component is large is if the it has over 400 lines of code.
Another way, which I find mostly useful, is if you find yourself trying to replicate (copy - pasting) some section of the component into another component. This is when you should evaluate whether to break down a component. So that each component, ideally performs a single function.
For our shopping site above, this would be having one component for search, another for looping through the individual products and another for displaying individual products. The last two can be reused in the search section and to display checkout cart.
Another important thing to do, is to ask whether the logic inside the component class, can benefit by moving it either to a class or a service. Things like HTTP calls to API should be in their own services, making them available to more components that may need them in the future. Basically, any logic that might be used by more than one component, doesn’t belong inside the component.
When breaking down components into smaller components, you find that you will need to pass data between components. One such scenarios is when want to pass data such as product information to product display component from parent.
You might also want to be able pass back data and events to parent component for action. The easiest way to achieve this is using Output and Input Bindings for parent-child components and using a service for unrelated components. I won’t go into details of this in this post, but here are some useful learning resources you can use:
You can also use directives and pipes to extract some functionality from components. Then the directives and pipes can be used in multiple components. You can have a directive to modify the behavior of a single button, in such a way that it behaves differently based on the situation.
For instance, when a product is being displayed inside the checkout cart, you need a remove button and not a buy button. With inbuild
directives such as
NgSwitch, you can easily achieve this. You can also build your own directive to achieve different functionality for different scenarios.
Pipes on the other hand are great for transforming values for display. Angular has inbuilt pipes to alter text case, format dates, subscribe to observables etc. You can build your own pipes to do more than that.
A good example where a pipe might be very useful is when you have country or currency codes but want to transform into known recognizable names. You can either create a method in your component to do this, but I find it better to use pipes in such circumstances. This way, anytime you wish to transform a value inside a template, you just add the pipe.
Lazy loading or deferred loading is a technique where you break up your application into smaller sections to improve performance. You can learn more about it here.
Normally, components (directive and pipes too) are registered in a single module. In an angular app without lazy loading, this is not a problem, because there is only one app module. If you try to register one of this three items in multiple modules, you will get an error that they cannot be registered in more than one module. Also, to use two components in a parent child relationship, they need to be registered in the same component.
To work around this, you need to create a shared module, where you declare and export the components, pipes and directives you want to share. Then, you can simply import the shared module into any of your lazy loaded modules and all exported items will be available. You can learn more about shared modules in Angular here.
NB: When using shared modules, remember to import the required modules required by the components.
As of Angular 6, they introduced Angular CLI Workspaces, allowing you to house more than one project in a single workspace. This means that if you have more than one project, you might want to share components across your projects. Angular 6 also introduced the ability to develop libraries within the same workspace.
And Angular CLI will register the library build directory (dist/library-name) in the tsconfig. This makes the library available to any project within the workspace after building it. This means that you can extract the components you want to share into a library. This library can then be privately used them within the project. There is no need to publish them anywhere, public or privately. You can learn more about building libraries in Angular here.
These are some of the techniques that I have come up with to make my components more reusable. They also have the added advantage of making my code cleaner and easily readable. This is important to me, since I don’t just want to develop web apps, but also enjoy the experience. If you have a suggestion on how to improve this, please leave it in the comment section below. Thank you for getting this far. If you have a topic suggestion you can also leave it the comment section below.