Agnostic components in Angular

Agnostic components in Angular

When you’re building a reusable components library, API is very important. Learn how to make components that work with everything and look like anything!

When you’re building a reusable components library, API is very important. On one hand, you want a tidy, reliable solution, on the other — you need to take care of lots of specific use cases. Learn how to make components that work with everything and look like anything!

When you’re building a reusable components library, API is very important. On one hand, you want a tidy, reliable solution, on the other — you need to take care of lots of specific use cases. And it’s not just about working with diverse data. Your components must be flexible visually. Besides, it has to be easy to update and deliver across projects.

These components must be customizable like no other. And it shouldn’t be hard to do — they will be used by senior and junior developers alike. Also, since one of the reasons to make such a library is to reduce code duplication, configuration must not turn into a copy-paste exercise.

Data-agnostic components#

Say you’re making a drop-down menu button. What would be its API? Surely it would need an array of items for the menu. Probably, the first run would be an interface like the following:

interface MenuItem {
    readonly text: string;
    readonly onClick(): void;

Fairly quickly, you’d add an option to disable an item. Then designers would come up with a menu with icons. Then they will draw them on the other side for the fellow project. The interface keeps growing, taking more and more cases into account. Great variety of flags turn your component into the United Nations assembly.

Looking familiar?

Generics to the rescue. If you build your component to not care about the data model at all — this problem seizes to exist. Instead of calling item.onClick it could emit clicked item. What to do with it is up to the library users. They are free to call item.onClick or organize their model differently.

In the case of disabled state, a component would use a handler. It’s a function that takes generic item as an argument and returns whether it is disabled or not. Handling different visual options would be explored later.

For a ComboBox, you could come up with an interface with string for display value and a property with the real value behind it. This seems reasonable. After all, when user types into ComboBox, options must be narrowed down by the string input.

interface ComboBoxItem {
    readonly text: string;
    readonly value: any;

You would soon uncover limitations of this approach once design pops up where string is not enough. Besides, form contains a wrapper instead of the real value and filtering is not always limited to string representation. You could filter by phone number contacts that show names. And each new component like that brings new interface even if the underlying model is the same.

Here you can also use generics and provide a stringify handler to the component: (item: T) => string. A simple String(item) would work by default. This way, you can even use classes for options by defining toString method. As mentioned earlier, string is not always enough to filter. It’s another good case for handlers — we could pass a matching function to ComboBox. It would take user input and item as arguments and return true if item fits.

Another example where interface is often used — unique id. You might get your value in one request and options later in another. Then you will have a copy of the selected item in the array, not the same reference. Instead of an id property, you could have an identity matching function. It would take two items as arguments with the default value of simple triple _`=` comparison._

Many components, such as tabs, radio buttons, variety of lists don’t need to be aware of the data model they work with. Abstraction over it allows to create extendable code not tied to concrete realization. This means there will be no breaking changes with added features. Users will not have to adapt their data and components fit together like Lego blocks.

The same options component could go in context menu, SelectMultiSelect. Atomic components effortlessly make up bigger structures. However, generic data must be displayed somehow. Lists could have avatars, different colors, unread messages counters and so on.

Example drop-down with custom design

To make this work, we need to approach presentation in the same manner as we took on generic data.

angular angular-templates angular-dynamic-components typescript api

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Top 10 API Security Threats Every API Team Should Know

Learn what are the most important API security threats engineering leaders should be aware of and steps you can take to prevent them

An API-First Approach For Designing Restful APIs | Hacker Noon

I’ve been working with Restful APIs for some time now and one thing that I love to do is to talk about APIs.

Public ASX100 APIs: The Essential List

The method used for this initial research was to obtain a list of the ASX100 (as of 18 September 2020). Then work through each company looking at the following

What Are Good Traits That Make Great API Product Managers

What is API product management and what can you be doing to be a better API product manager — get aligned with SaaS and enterprise software requirements. This guide lays out what is API product management and some of the things you should be doing to be a good product manager.

Install Angular - Angular Environment Setup Process

Install Angular in easy step by step process. Firstly Install Node.js & npm, then Install Angular CLI, Create workspace and Deploy your App.