Let's build - Feature flags in Angular
Tags: typescipt, angular
Published: 2023-06-24 15:03:01

---
title: Let's build - Feature flags in Angular
published: true
description: A simple feature flag implementation in Angular
series: Let's build
tags: Typescipt, Angular
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
# published_at: 2023-06-24 10:39 +0000
---
# The problem
In one of the projects I'm working on we wanted to show/hide certain elements/features at runtime.
The requirements were pretty simple:
1. Manually enable and disable the toggle in a configuration file 
2. It should be possible to change the value at runtime

# Solution
A well known solution for this are Feature Flags or Feature Toggles. A lot has already been written about this topic e.g. you can find some details [here](https://martinfowler.com/articles/feature-toggles.html).
There are quite some ready made solutions out there. However most of the available solutions are SaaS offerings and these are not always an option (for technical or financial reasons).
So, as we don't have many (complicated) requirements, it shouldn't be too hard to build our own, local version.

# Overview
The following diagram gives an overview of the main elements
![Overview](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a788zeit2vo1oasfyr8p.png) 
As mentioned previously, we are aiming for a rather simple solution so there is not too much going on.

# Implementation

## Store
All of the configuration is stored in the `feature.json` file. It has a pretty simple structure with the key being the name of the feature and the value a boolean which indicates if the feature is enabled or not.
This is enough for basic use cases. However if there are a lot flags it could make sense to add bit more structure here e.g. nesting the different flags under a key which represents the pages or components they are associated with.

It is also possible to define different `feature.json` files as a sort of template for a specific configuration e.g. if the application is deployed for multiple customers.

```json
{
  "newFeature": true
}

```

## FeatureService

### Bootstrapping
The root injected service loads the `feature.json` file and stores it in memory.
The file could be validated and typed after loading (e.g. using something like [zod](https://github.com/colinhacks/zod)).
I personally did not see any advantage in doing that as the file is only used in the `isFeatureEnabled` method which checks if the provided key is truthy. Having it typed would not give any benefit and has the drawback that the validation and type definition has to be updated whenever a new property is added to the `feature.json` file.

```typescript
  init(): Observable<void> {
    const result = new ReplaySubject<void>(1);
    this.http
      .get<typeof this.featuresFlags>('assets/feature.json')
      .pipe(
        first(),
        catchError(() => of({}))
      )
      .subscribe((featureFlags) => {
        this.featuresFlags = featureFlags;
        result.next();
        result.complete();
      });
    return result;
  }
```
For the sake of the example the loading mechanismn is kept pretty simple (e.g. it does not include any error handling, it hard codes the path...).

The init method is called by an `APP_INITIALIZER` at application start up.
It returns an `Observable` to make sure the first render does not happen before the `feature.json` file has been loaded.

```typescript
const initFeatureServiceFactory = (featureService: FeatureService) => {
  return () => featureService.init();
};

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    HttpClientModule,
    WithoutDirectiveComponent,
    WithDirectiveComponent,
  ],
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: initFeatureServiceFactory,
      deps: [FeatureService],
      multi: true,
    },
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}
```

### IsFeatureEnabled
The aformentioned `isFeatureEnabled` method returns if the feature is enabled or not. 
The implementation is pretty straight forward at the moment:

```typescript
  isFeatureEnabled(name: string): boolean {
    return this.featuresFlags[name];
  }
```

Having a dedicated function hides the storage mechanism and allows for changing to a different approach in the future with minor impact on the using components.

## Components
For demonstration purposes two components have been added to the project

### WithoutDirectiveComponent
As the name implies the component does the feature check for itself by directly calling the `isFeatureEnabled` with the feature name. 

```typescript
export class WithoutDirectiveComponent {
  isNewFeatureEnabled = false;

  constructor(public featureService: FeatureService) {
    this.isNewFeatureEnabled = this.featureService.isFeatureEnabled('newFeature');
  }

```

```html
<p *ngIf="isNewFeatureEnabled; else featureDisabled">
  WithoutDirectiveComponent: Feauture enabled
</p>
<ng-template #featureDisabled>
  <p>WithoutDirectiveComponent: Feature disabled</p>
</ng-template>
```

 


### FeatureDirective
Repeating the "check and render" is a bit tedious and identical for every using component. Therefore a directive has been added to the project that takes care of this part. It's working similar to `ngIf`  but takes the feature name instead of a `boolean`.

The directive passes the provided feature name to the `FeatureService` and leverages the `ngIf` directive for hiding or showing the feature flagged element.
Similar to `ngIf` it also allows for displaying an alternative `template` should the feature be disabled.

```typescript
@Directive({
  selector: '[appIfFeatureEnabled]',
  standalone: true,
  hostDirectives: [
    {
      directive: NgIf,
      inputs: ['ngIfElse: appIfFeatureEnabledElse'],
    },
  ],
})
export class IfFeatureEnabledDirective {
  @Input() set appIfFeatureEnabled(appIfFeatureEnabled: string) {
    this.ngIf.ngIf = this.featureService.isFeatureEnabled(
      appIfFeatureEnabled ?? false
    );
  }

  constructor(private ngIf: NgIf, private featureService: FeatureService) {}
}
```

### WithDirectiveComponent
The component just needs to pass to feature name to the `FeatureDirective`

```html
<p *appIfFeatureEnabled="'newFeature'; else featureDisabled">
  WithDirectiveComponent: Feature enabled
</p>
<ng-template #featureDisabled
  >WithDirectiveComponent: Feature disabled</ng-template
>
```

# Conclusion
This is it, a simple solution for feature flagging templates elements in Angular.
As mentioned in the beginning, the implementation only covers simple hide/show use cases which can often be enough, especially in the beginning.
In our project, it has served us as well so far.
It was easy and fast to build, it's easy to maintain (e.g. adding new feature flags) and avoids adding another dependency to a third party library (or company) and, most importantly, it fulfils all of our current requirements.

The code can be found [here](https://github.com/remshams/angular-feature-flags)