Three Japanese and Korean Beauty Rebuilt Brands in Q1

After experiencing the impact of general environment in recent years, Japanese and Korean brands are seeking to “innovate”. Recently, CHAILEEDO found that in the first quarter of 2023, three…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




Versioning features in an angular app

Imagine a scenario where your app needs to show different versions of a component or services to different groups of users. If it sounds a bit farfetched, take the following scenario that was proposed to our development team in some real project:

The naive approach of having ngIf directives all over the place can work for the simpler cases but it would be hard to maintain and would also clutter our beautiful templates. Also, components using different services when switching from one version to another would be very difficult to maintain.

So we came up to the following approach, to cope with all those situations:

To illustrate this post, we created an app. Our app proudly shows some country data, like a country flag, area and population. We made contact with governments all over the world and kindly asked them to join our non-profit revolutionary app, providing some basic data:

Some of these countries have really severe regulations and wanted to join the app, but without revealing their area and population initially, until their lawyers would determine if this data could be displayed. So we designed the first version of the app with a single screen, where the user would select the country from a select combo box, and a component with two subcomponents displaying the country data:

The content component should be optional, and will display depending on the country’s regulations.

These are some screenshots of the app at this point:

After the kick off, some users were so excited that started to ask for some new features:

The development team agreed that, given that some countries still had not provided their area and population, it was reasonable to think that some of them would not provide instantly their flag, capital and anthem. So we decided to version the header and content components, so we could give them a smooth path to upgrade their data, while still looking good in the app, showing the old components instead of new components with empty fields.

These are some screenshots of the final version of the app:

With that in mind, let’s see the FeatureIf directive. It will display an element if the feature is enabled for the country. Optionally, we can define the minimum version implemented by the country, meaning that if the country uses a lower version, the element will be hidden.

I will skip the standard imports to save space in the listing:

This structural directive makes use of 4 parameters: featureName, countryCode, featureVersion and else. Pay attention on how we define input properties in a structural directive:

Please remark below how the directive is used in a template. The first parameter doesn’t need a key, while the rest is passed with “key: value” tuples, separated by a semicolon (;).

What the directive basically does is:

In the parent component, we use the directive with the else parameter set to true, to display an informative text when the content component is not available.

Our second directive will allow us to dynamically inject a component or another, depending on some parameters.

This time, the directive takes three parameters: featureName, countryCode and data. The data parameter will be used to pass data to our dynamic component. Since different components may have different inputs, we took the approach of receiving any external data through this data object. Dynamic components may also receive external data through services, as we will see later.

So basically, what this directive does is:

Let’s see the code for those DynamicComponent and DynamicComponentService classes.

The DynamicComponent is just a class with a public data property. We will also create a dictionary interface and a constant with the current dynamic component classes (country content version 1 and 2) that will be used by the service.

The DynamicComponentService simply returns the appropriate component class, depending on the featureName and version parameters.

Let’s see how this directive is used in the parent component.

This is the code for the CountryContentV1Component class.

And this is how the template uses the data property to display the country data.

You can see a demo of the application here:

The situation can get a bit more complicated if services are also versioned. Let’s imagine that the first version of the service providing country data just included the country name, area and population, and that a new version should be created to include the new data, while still providing the old version for backward compatibility.

In this case we can inject the corresponding service version in the versioned components. We won’t be using the data property from DynamicComponent, but will get the data from the service instead. We could also use injection tokens to dynamically inject the versioned service depending on certain conditions.

The following demo is a simple approach using versioned services.

The demo app is probably too simple for that kind of solution. We could still smartly use some ngIf and ngTemplate stuff to get to the same solution. But think of a case where the user doesn’t select the country from a combo box, but the country gets auto detected from your device settings, and think of a more complicated UI with a dashboard with several widgets that should be displayed or hidden, or have different content according to the country, and then this approach will make much more sense.

This post is long enough to get into more details. If you have suggestions to enhance it, please include them in your comments :)

More on angular dynamic components:

More on feature versioning:

Add a comment

Related posts:

EVERYTHING YOU NEED TO KNOW ABOUT POETRY IN 3 MINUTES

EVERYTHING YOU NEED TO KNOW ABOUT POETRY IN 3 MINUTES. In honor of April being National Poetry Month, here’s a crash course in ever popular art form..

Audit by design

Imagine a company in its annual report claiming to have reduced its CO2 emissions by 25%. You assume that this claim has been audited by their accountant. The accountant has sent an auditor to check…

Religion by Habbit

An individual withholds certain beliefs and ideas about his/her idle lifetime. Many people live life with passion and intuition while many follow a set of cautious principles to live a well-set life…