Hone logo
Hone
Problems

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:

  1. mySwitch Directive:

    • 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.
  2. mySwitchCase Directive:

    • 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 with mySwitchOf, should cause this element to be displayed.
    • If no mySwitchCase matches, and a mySwitchDefault directive is present, the element with mySwitchDefault should be displayed.
  3. mySwitchDefault Directive (Optional but recommended):

    • This directive will be applied to an element that should be displayed when no mySwitchCase matches.
    • It does not need to accept any input properties.

Expected Behavior:

  • The mySwitch directive should iterate through its children.
  • For each child with a mySwitchCase directive, it should compare the mySwitchCase value with the mySwitchOf value.
  • If a match is found, the corresponding mySwitchCase element should be rendered (made visible). All other mySwitchCase elements (and the mySwitchDefault element if present) should be hidden.
  • If no mySwitchCase matches, and a mySwitchDefault element is present, it should be rendered. All mySwitchCase elements should be hidden.
  • If no mySwitchCase matches and no mySwitchDefault is present, nothing will be rendered within the mySwitch container.

Important Considerations:

  • You will need to manage the visibility of elements. Using *ngIf directly within the directives is not the goal here; you should manage the DOM element's presence or visibility directly. A common approach is to use ViewContainerRef to manipulate the DOM.
  • Ensure that only one mySwitchCase or mySwitchDefault is 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 @Directive decorator.
  • You should use TypeScript for implementation.
  • Avoid using the built-in *ngSwitch, *ngSwitchCase, and *ngSwitchDefault directives in your solution's template. You are reimplementing their logic.
  • For managing element visibility, consider using ViewContainerRef and TemplateRef.

Notes

  • This challenge tests your understanding of Angular directives, input properties, and DOM manipulation within Angular.
  • Think about how you would manage multiple mySwitchCase directives 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.
Loading editor...
typescript