Hone logo
Hone
Problems

Implementing a @switch Directive in Angular

Angular lacks a native @switch syntax similar to those found in other languages. This challenge asks you to create a custom Angular directive that mimics this functionality, allowing for cleaner and more readable conditional rendering based on a single expression. This directive will simplify complex *ngIf chains and improve the maintainability of your templates.

Problem Description

You need to implement an Angular directive called @switch that takes a single expression as input. This expression will be evaluated, and the directive will render the first *ngSwitchCase that matches the expression's value. You'll also need to implement the corresponding *ngSwitchCase directive to define the conditions and their associated templates. The directive should handle cases where no matching *ngSwitchCase is found, rendering a default template defined by *ngSwitchDefault.

What needs to be achieved:

  • Create an @switch directive that accepts an expression.
  • Create an ngSwitchCase directive that matches against the expression provided to the @switch directive.
  • Create an ngSwitchDefault directive that renders when no ngSwitchCase matches.
  • The @switch directive should dynamically render the appropriate *ngSwitchCase or *ngSwitchDefault based on the expression's value.

Key Requirements:

  • The @switch directive should accept a single expression as input (e.g., @switch(myValue)).
  • The ngSwitchCase directive should accept a value to match against (e.g., *ngSwitchCase="value1").
  • The ngSwitchDefault directive should render when no other ngSwitchCase matches (e.g., *ngSwitchDefault).
  • The directive should work with any data type that can be compared using the === operator.
  • The directive should be reusable and not rely on any specific component or service.

Expected Behavior:

When the @switch directive is used, it should evaluate the expression and render the first *ngSwitchCase whose value matches the expression. If no ngSwitchCase matches, the *ngSwitchDefault should be rendered. Changes to the expression should trigger re-evaluation and update the rendered template accordingly.

Edge Cases to Consider:

  • The expression evaluates to null or undefined.
  • The expression is a complex object.
  • No ngSwitchCase or ngSwitchDefault is provided.
  • Multiple ngSwitchCase directives have the same value. (Only the first one should be rendered).
  • The expression is a string and needs to be compared case-sensitively.

Examples

Example 1:

Input:
<div *switch="status">
  <div *ngSwitchCase="1">Status is 1</div>
  <div *ngSwitchCase="2">Status is 2</div>
  <div *ngSwitchDefault>Status is unknown</div>
</div>
status = 1

Output:
<div>Status is 1</div>

Explanation: The expression `status` evaluates to `1`, which matches the first `ngSwitchCase` with the value `1`. Therefore, "Status is 1" is rendered.

Example 2:

Input:
<div *switch="fruit">
  <div *ngSwitchCase="'apple'">Apple</div>
  <div *ngSwitchCase="'banana'">Banana</div>
  <div *ngSwitchDefault>Unknown Fruit</div>
</div>
fruit = 'orange'

Output:
<div>Unknown Fruit</div>

Explanation: The expression `fruit` evaluates to 'orange', which does not match either `ngSwitchCase`. Therefore, the `ngSwitchDefault` is rendered.

Example 3:

Input:
<div *switch="user.role">
  <div *ngSwitchCase="'admin'">Admin Panel</div>
  <div *ngSwitchCase="'user'">User Dashboard</div>
  <div *ngSwitchDefault>Guest Access</div>
</div>
user = { role: 'guest' }

Output:
<div>Guest Access</div>

Explanation: The expression `user.role` evaluates to 'guest', which does not match either `ngSwitchCase`. Therefore, the `ngSwitchDefault` is rendered.

Constraints

  • The solution must be implemented in TypeScript.
  • The directive and its associated directives must be standalone.
  • The solution should be efficient and avoid unnecessary DOM manipulations.
  • The code should be well-documented and easy to understand.
  • The solution should be compatible with Angular versions 14 and above.

Notes

  • Consider using Angular's TemplateRef and ViewContainerRef to dynamically render templates.
  • Think about how to handle the expression evaluation and comparison within the directives.
  • Pay close attention to the order of ngSwitchCase directives, as only the first match should be rendered.
  • This is a good opportunity to practice creating custom Angular directives and understanding how they interact with templates. Focus on clean, readable code and proper error handling.
Loading editor...
typescript