Angular Directives
Angular uses directives to add additional behavior to elements. There are several built-in directives that help manage different aspects of your application.
Directive types
Directive Type | Details | Example |
---|---|---|
Components | Used with a template. This type of directive is the most common directive type. | Any angular component |
Attributes directives | Change the appearance or behavior of an element, component, or another directive. | NgClass NgStyle, NgModel |
Structural directives | Change the DOM layout by adding and removing DOM elements. | ngIf, ngFor |
Our focus will be on Structural directives, so let us take a deep dive into them.
Why Do We Need Structural Directives?
Structural directives are useful when we want to dynamically change the structure of the HTML Document Object Model (DOM) by adding, removing, or transforming elements based on a condition or data.
Key reasons for using structural directives
- Conditional rendering
- Dynamic lists
- Managing DOM structure
- Reusability
Toggle This: What Are Feature Flags?
Feature flags are a software development technique that allows teams to enable or disable specific features in an application at runtime, without changing or redeploying the code.
In Angular, feature flags are implemented as custom structural directives. They are similar to ngIf, but with key differences.
How does the two differ
Purpose
ngIf: Used for conditional rendering based on a boolean expression in the code. It primarily controls UI elements based on local component state or simple logic.
Feature Flags: A mechanism to remotely enable or disable features in an application without requiring a new deployment. They help manage features across different environments, support A/B testing, and enable progressive rollouts.
Control Mechanism
ngIf: The condition for *ngIf is determined by a boolean expression directly within your Angular template or component logic. Changes require modifying the code and redeploying the application.
Feature Flags: The state of a feature flag is typically managed externally, often through a dedicated feature flag service or platform. This allows toggling features on or off at runtime without code changes or redeployments.
Implementation
To create a directive, you can use the Angular CLI as follows:
ng generate directive <directive-name> --standalone
The following class should be generated.
@Directive({
selector: '[appFeatureFlag]',
standalone: true,
})
export class FeatureFlagDirective implements OnInit, OnDestroy {
@Input('appFeatureFlag') featureFlag!: string;
The @Directive decorator registers this class as a directive. The selector is the directive name (appFeatureFlag). The @Input decorator allows Angular to pass a value when the directive is used.
Directive Logic
private subscription?: Subscription;
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef,
private featureFlagService: FeatureFlagService
) {}
public ngOnInit() {
if (!this.featureFlag) {
this.viewContainer.clear();
return;
}
this.subscription = this.featureFlagService
.hasAccess(this.featureFlag)
.subscribe((hasAccess) => {
this.viewContainer.clear();
if (hasAccess) {
this.viewContainer.createEmbeddedView(this.templateRef);
}
});
}
Explanation: On initialization, we clear the viewContainer, which effectively removes a component or element from the DOM. Then, if a feature flag is provided, we check access and render the component only if access is granted.
Deep Dive To a Feature Flag Service
private checkFullPath(nodes: ItemNames[] | undefined, segments: string[]): boolean {
if (!nodes) {
return false;
}
const [current, ...rest] = segments;
for (const node of nodes) {
if (node.name === current) {
// Recurse into children for the remaining segments
if (rest.length === 0) {
return true; // Last segment matched
}
if (node.itemNames && node.itemNames.length > 0) {
return this.checkFullPath(node.itemNames, rest);
} else {
return false; // No children to match remaining segments
}
}
}
return false; // Current segment not found
}
Explanation: Due to the hierarchical structure of features, we split the feature flag into segments and recursively check each parent and its children to confirm if a feature is accessible.
Pros and Cons of feature flags
Pros
- Dynamic Control: Features can be turned on or off without redeploying code.
- Safe Rollouts: Supports progressive feature rollouts and A/B testing.
- Environment Flexibility: Different features can be enabled for different environments or user groups.
- Reduced Risk: Bugs in new features can be quickly disabled without impacting the whole system.
Cons
- Increased Complexity: Managing many flags can make the codebase harder to maintain.
- Technical Debt: Old or unused flags need to be cleaned up to prevent clutter.
- Testing Challenges: Testing all combinations of feature flags can be complex.
- Performance Overhead: Frequent checks on feature flags might introduce minimal runtime overhead.
Here is a fronend code: https://github.com/mthobisig8/feature-flag-fe
Top comments (0)