Hone logo
Hone
Problems

Dynamic Component Loading in Angular

Angular's powerful component-based architecture allows for building flexible and interactive user interfaces. A common requirement is to dynamically load and render components based on runtime conditions, such as user input or data fetched from an API. This challenge will test your ability to implement dynamic component loading in Angular.

Problem Description

Your task is to create an Angular application that can dynamically load and render different components within a designated container. You will be provided with a list of available components and a mechanism to trigger the loading of a specific component. The application should be able to:

  • Define a set of available components: These components will be registered and accessible for dynamic loading.
  • Create a container for dynamic components: A specific directive or component will act as the host where the dynamically loaded components will be rendered.
  • Implement a mechanism to trigger component loading: This could be a button click, a dropdown selection, or any other user interaction.
  • Dynamically instantiate and render the selected component: Based on the trigger, the application should create an instance of the specified component and attach it to the designated container.
  • Handle component inputs and outputs: If the dynamically loaded components require input data or emit output events, your solution should correctly manage these.
  • Clean up/destroy loaded components: When a new component is loaded or the container is no longer needed, the previously loaded component should be properly destroyed.

Examples

Example 1: Basic Component Loading

Scenario: Load a WelcomeMessageComponent when a button is clicked.

Input:

  • A button with the text "Load Welcome Message".
  • A DynamicHostDirective attached to an empty ng-container.
  • A DynamicComponentLoaderService that knows about WelcomeMessageComponent.

Expected Behavior: Clicking the "Load Welcome Message" button should cause WelcomeMessageComponent to be rendered inside the ng-container.

Example 2: Loading Components with Inputs

Scenario: Load a UserProfileComponent with user data passed as input.

Input:

  • A dropdown allowing selection of a user (e.g., "Alice", "Bob").
  • A DynamicHostDirective attached to an empty div.
  • A DynamicComponentLoaderService that knows about UserProfileComponent.
  • User data: { id: 1, name: 'Alice', email: 'alice@example.com' } and { id: 2, name: 'Bob', email: 'bob@example.com' }.

Expected Behavior: Selecting "Alice" from the dropdown should render UserProfileComponent with Alice's data. Selecting "Bob" should destroy the previous instance and render UserProfileComponent with Bob's data.

Example 3: Dynamic Component with Output Event

Scenario: Load an InteractiveButtonComponent that emits an event when clicked.

Input:

  • A button labeled "Show Interactive Button".
  • A DynamicHostDirective.
  • An InteractiveButtonComponent that has an @Output() clicked = new EventEmitter<string>();.
  • The application should display a message indicating which button was clicked.

Expected Behavior: Clicking "Show Interactive Button" renders InteractiveButtonComponent. Clicking the rendered button inside InteractiveButtonComponent should emit an event, and the parent component should update to show a message like "Interactive button clicked with label: Click Me!".

Constraints

  • The solution must be implemented using Angular version 14 or later.
  • All dynamic component loading logic should be encapsulated within a service for reusability.
  • Components should be loaded lazily if possible, although eager loading for demonstration is acceptable.
  • The application should handle cases where the requested component is not found.
  • The solution should be well-tested with unit tests covering the dynamic loading service and directive.

Notes

Consider using ViewContainerRef and ComponentFactoryResolver (or the newer approach with createComponent in Angular 13+) for dynamic component instantiation. Think about how to map component identifiers (e.g., strings) to their actual component classes. Pay attention to the lifecycle hooks of dynamically loaded components.

Loading editor...
typescript