Hone logo
Hone
Problems

Angular Style Optimization Challenge

This challenge focuses on optimizing the styling of an Angular application to improve performance and maintainability. You will implement a system to dynamically apply and remove CSS classes based on component state and user interactions, ensuring efficient rendering and a clean codebase. This is crucial for creating responsive and performant user interfaces.

Problem Description

Your task is to build a reusable Angular directive that allows components to dynamically apply and remove a specified CSS class. The directive should toggle the class based on a boolean input property. This will enable components to manage their visual states efficiently without directly manipulating the DOM's class list.

Key Requirements:

  • Create a custom Angular directive named StyleTogglerDirective.
  • The directive should accept a boolean input property, let's call it applyClass.
  • When applyClass is true, the directive should add a specified CSS class to the host element.
  • When applyClass is false, the directive should remove the specified CSS class from the host element.
  • The directive needs to accept the name of the CSS class to be toggled as another input property, let's call it toggleClass.
  • The directive should handle initial rendering correctly, applying the class if applyClass is true on component initialization.
  • The directive should efficiently update the host element's classes when the applyClass input property changes.

Expected Behavior:

An element with the StyleTogglerDirective will have its specified CSS class added or removed solely based on the value of the applyClass input property.

Edge Cases:

  • What happens if toggleClass is not provided? The directive should ideally not throw an error and gracefully handle this situation (e.g., by not applying any class).
  • What if applyClass is initially true? The class should be applied upon directive initialization.

Examples

Example 1:

Scenario: A button that changes its appearance when clicked.

Component's TS:

import { Component } from '@angular/core';

@Component({
  selector: 'app-my-button',
  template: `
    <button
      [applyClass]="isActive"
      toggleClass="active-button"
      style="padding: 10px; border: 1px solid black;"
    >
      Click Me
    </button>
  `,
  styles: [`
    .active-button {
      background-color: lightgreen;
      font-weight: bold;
    }
  `]
})
export class MyButtonComponent {
  isActive = false;

  toggleActive() {
    this.isActive = !this.isActive;
  }
}

Explanation: The button element has the StyleTogglerDirective. Initially, isActive is false, so the active-button class is not applied. When the user interacts (e.g., clicks the button, triggering toggleActive), isActive becomes true, and the active-button class is added to the button element. The directive manages this class addition/removal.

Example 2:

Scenario: Highlighting an invalid form input.

Component's TS:

import { Component } from '@angular/core';

@Component({
  selector: 'app-input-field',
  template: `
    <input
      type="text"
      [applyClass]="isInvalid"
      toggleClass="error-input"
      style="border: 1px solid grey; padding: 5px;"
    />
    <p *ngIf="isInvalid" style="color: red;">Please enter a valid value.</p>
  `,
  styles: [`
    .error-input {
      border-color: red !important;
    }
  `]
})
export class InputFieldComponent {
  isInvalid = true; // Assume input is initially invalid
}

Explanation: The input element uses StyleTogglerDirective. isInvalid is true on initialization, so the error-input class is applied, changing the input's border color to red. If isInvalid were to become false (e.g., after user correction), the error-input class would be removed.

Example 3:

Scenario: Using the directive without specifying toggleClass.

Component's TS:

import { Component } from '@angular/core';

@Component({
  selector: 'app-no-class',
  template: `
    <div [applyClass]="showHighlight" style="padding: 10px; background-color: yellow;">
      This div might be highlighted.
    </div>
  `,
  styles: [`
    /* No specific styles defined for a class name as it's not provided */
  `]
})
export class NoClassComponent {
  showHighlight = true;
}

Explanation: The div has applyClass set to true. However, since toggleClass is not provided, the directive will not attempt to add or remove any specific class. The div will retain its default styling. This demonstrates graceful handling of missing input.

Constraints

  • The directive must be implemented as a standalone directive or within a module.
  • The directive should not directly manipulate the DOM using ElementRef if a more Angular-idiomatic approach (like Renderer2) is available.
  • The solution should be written in TypeScript.
  • Performance is important: avoid unnecessary DOM manipulations. The directive should only update the class list when applyClass or toggleClass changes.

Notes

  • Consider using OnChanges lifecycle hook to react to input property changes.
  • Renderer2 is a good tool for manipulating the DOM in a platform-agnostic way within Angular.
  • Think about how to handle the directive's initial state.
  • A clean implementation will be testable and easy to integrate into other components.
Loading editor...
typescript