Replicate Angular's ngSwitch Directive
This challenge asks you to implement a custom directive that mimics the functionality of Angular's built-in ngSwitch directive. This is a fundamental directive for conditional rendering based on a specific value, making it crucial for dynamic UIs.
Problem Description
You need to create a custom directive in Angular that behaves like ngSwitch. This directive will allow you to conditionally display different content based on the value of a variable. The directive will consist of two parts: a parent directive (mySwitch) and a child directive (mySwitchCase).
Key Requirements:
-
mySwitchDirective:- This directive will be applied to a container element.
- It will accept an input property, let's call it
mySwitchOf, which will hold the value to be compared.
-
mySwitchCaseDirective:- This directive will be applied to elements that should be conditionally rendered.
- It will accept an input property, let's call it
mySwitchCase, which will specify the value that, when matched withmySwitchOf, should cause this element to be displayed. - If no
mySwitchCasematches, and amySwitchDefaultdirective is present, the element withmySwitchDefaultshould be displayed.
-
mySwitchDefaultDirective (Optional but recommended):- This directive will be applied to an element that should be displayed when no
mySwitchCasematches. - It does not need to accept any input properties.
- This directive will be applied to an element that should be displayed when no
Expected Behavior:
- The
mySwitchdirective should iterate through its children. - For each child with a
mySwitchCasedirective, it should compare themySwitchCasevalue with themySwitchOfvalue. - If a match is found, the corresponding
mySwitchCaseelement should be rendered (made visible). All othermySwitchCaseelements (and themySwitchDefaultelement if present) should be hidden. - If no
mySwitchCasematches, and amySwitchDefaultelement is present, it should be rendered. AllmySwitchCaseelements should be hidden. - If no
mySwitchCasematches and nomySwitchDefaultis present, nothing will be rendered within themySwitchcontainer.
Important Considerations:
- You will need to manage the visibility of elements. Using
*ngIfdirectly within the directives is not the goal here; you should manage the DOM element's presence or visibility directly. A common approach is to useViewContainerRefto manipulate the DOM. - Ensure that only one
mySwitchCaseormySwitchDefaultis visible at a time.
Examples
Example 1: Basic Usage
Component Template:
<div [mySwitchOf]="selectedTab">
<div *mySwitchCase="'home'">Home Content</div>
<div *mySwitchCase="'profile'">Profile Content</div>
<div *mySwitchCase="'settings'">Settings Content</div>
</div>
Component Class:
export class MyComponent {
selectedTab: string = 'profile';
}
Output:
The div with "Profile Content" will be displayed. The "Home Content" and "Settings Content" divs will not be rendered.
Explanation:
The mySwitchOf input of the mySwitch directive is set to 'profile'. The mySwitchCase directive on the "Profile Content" div matches this value, so that div is rendered.
Example 2: Using mySwitchDefault
Component Template:
<div [mySwitchOf]="userRole">
<div *mySwitchCase="'admin'">Admin Panel</div>
<div *mySwitchCase="'editor'">Editor View</div>
<div *mySwitchDefault>Unauthorized Access</div>
</div>
Component Class:
export class MyComponent {
userRole: string = 'guest';
}
Output:
The div with "Unauthorized Access" will be displayed. The "Admin Panel" and "Editor View" divs will not be rendered.
Explanation:
The mySwitchOf value ('guest') does not match any of the mySwitchCase values. Therefore, the mySwitchDefault content is rendered.
Example 3: Dynamic Value Change
Component Template:
<button (click)="changeTab('settings')">Go to Settings</button>
<div [mySwitchOf]="currentPage">
<div *mySwitchCase="'dashboard'">Dashboard</div>
<div *mySwitchCase="'settings'">Settings</div>
</div>
Component Class:
export class MyComponent {
currentPage: string = 'dashboard';
changeTab(tab: string) {
this.currentPage = tab;
}
}
Output:
Initially, "Dashboard" is displayed. When the button is clicked, changeTab('settings') is called, currentPage becomes 'settings', and the "Settings" div will be displayed, hiding the "Dashboard" div.
Explanation:
Angular's change detection will trigger the re-evaluation of the mySwitch directive when currentPage changes. The directive will then update the rendered content accordingly.
Constraints
- Your custom directives must be implemented using Angular's
@Directivedecorator. - You should use TypeScript for implementation.
- Avoid using the built-in
*ngSwitch,*ngSwitchCase, and*ngSwitchDefaultdirectives in your solution's template. You are reimplementing their logic. - For managing element visibility, consider using
ViewContainerRefandTemplateRef.
Notes
- This challenge tests your understanding of Angular directives, input properties, and DOM manipulation within Angular.
- Think about how you would manage multiple
mySwitchCasedirectives and ensure only one is active. - Consider the lifecycle hooks of directives for proper initialization and updates.
- The
*syntax in the example templates implies structural directives. Your implementation should achieve the same structural manipulation.