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
@switchdirective that accepts an expression. - Create an
ngSwitchCasedirective that matches against the expression provided to the@switchdirective. - Create an
ngSwitchDefaultdirective that renders when nongSwitchCasematches. - The
@switchdirective should dynamically render the appropriate*ngSwitchCaseor*ngSwitchDefaultbased on the expression's value.
Key Requirements:
- The
@switchdirective should accept a single expression as input (e.g.,@switch(myValue)). - The
ngSwitchCasedirective should accept a value to match against (e.g.,*ngSwitchCase="value1"). - The
ngSwitchDefaultdirective should render when no otherngSwitchCasematches (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
nullorundefined. - The expression is a complex object.
- No
ngSwitchCaseorngSwitchDefaultis provided. - Multiple
ngSwitchCasedirectives 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
TemplateRefandViewContainerRefto dynamically render templates. - Think about how to handle the expression evaluation and comparison within the directives.
- Pay close attention to the order of
ngSwitchCasedirectives, 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.