Skip to content

Feature Flags Tool

The Feature Flags tool allows developers to override feature flag states at runtime during development and testing. This enables testing different feature combinations without modifying backend configuration or redeploying applications.

  • Testing New Features: Enable experimental features during development without modifying backend configuration
  • Debugging: Quickly enable/disable features to isolate bugs in production-like environments
  • Demo Preparation: Force-enable premium features for demos without changing your environment
  • Edge Case Testing: Test application behavior with different flag combinations
app.component.ts
import { Component, inject, OnInit } from '@angular/core';
import { ToolbarFeatureFlagService } from 'ngx-dev-toolbar';
@Component({
selector: 'app-root',
template: `
<div>
@if (darkModeEnabled) {
<p>Dark mode is enabled!</p>
}
</div>
`
})
export class AppComponent implements OnInit {
private featureFlagsService = inject(ToolbarFeatureFlagService);
darkModeEnabled = false;
ngOnInit() {
// Define available feature flags
this.featureFlagsService.setAvailableOptions([ // [!code highlight]
{
id: 'dark-mode',
name: 'Dark Mode',
description: 'Enable dark theme',
isEnabled: false,
isForced: false
},
{
id: 'new-ui',
name: 'New UI',
description: 'Enable redesigned interface',
isEnabled: false,
isForced: false
}
]);
// Subscribe to all values with overrides applied (recommended)
this.featureFlagsService.getValues().subscribe(flags => { // [!code highlight]
const darkMode = flags.find(f => f.id === 'dark-mode');
this.darkModeEnabled = darkMode?.isEnabled || false;
});
}
}
feature-flag.service.ts
import { Injectable, inject, signal, computed } from '@angular/core';
import { ToolbarFeatureFlagService } from 'ngx-dev-toolbar';
@Injectable({ providedIn: 'root' })
export class FeatureFlagService {
private toolbarService = inject(ToolbarFeatureFlagService);
private flags = signal<Map<string, boolean>>(new Map());
// Computed signals for specific features
isDarkModeEnabled = computed(() => this.flags().get('dark-mode') ?? false);
isNewUIEnabled = computed(() => this.flags().get('new-ui') ?? false);
initialize(availableFlags: { id: string; name: string; defaultValue: boolean }[]) {
// Set available options in toolbar
this.toolbarService.setAvailableOptions(
availableFlags.map(flag => ({
id: flag.id,
name: flag.name,
isEnabled: flag.defaultValue,
isForced: false
}))
);
// Subscribe to all values with overrides applied
this.toolbarService.getValues().subscribe(allFlags => {
const flagMap = new Map<string, boolean>();
allFlags.forEach(flag => flagMap.set(flag.id, flag.isEnabled));
this.flags.set(flagMap);
});
}
isEnabled(flagId: string): boolean {
return this.flags().get(flagId) ?? false;
}
}
  • Always provide meaningful names and descriptions for feature flags
  • Use computed signals for reactive flag state management
  • Initialize flags early in application lifecycle (app initialization or root component)
  • Subscribe to forced values to get toolbar overrides
  • Persist flag state across page reloads (handled automatically by the toolbar)

The toolbar can persist forced flag values back to your actual data source (e.g., a backend API or config file). When configured, each flag item shows an “apply” button that triggers your callback.

Call setApplyToSource() on the service — right alongside setAvailableOptions():

feature-flag.service.ts
import { Injectable, inject } from '@angular/core';
import { ToolbarFeatureFlagService } from 'ngx-dev-toolbar';
@Injectable({ providedIn: 'root' })
export class FeatureFlagService {
private toolbarService = inject(ToolbarFeatureFlagService);
constructor() {
this.toolbarService.setAvailableOptions([...]); // [!code highlight]
this.toolbarService.setApplyToSource(async (flagId, value) => { // [!code highlight]
await fetch(`/api/feature-flags/${flagId}`, { // [!code highlight]
method: 'PUT', // [!code highlight]
body: JSON.stringify({ enabled: value }), // [!code highlight]
}); // [!code highlight]
}); // [!code highlight]
}
}

The toolbar automatically manages loading, success, and error states for each item. If the callback throws, the item shows an error indicator.

The Feature Flags tool integrates seamlessly with Angular’s reactive state management using signals and observables. When a flag is toggled in the toolbar, your application receives the updated state through the getForcedValues() observable.