Hone logo
Hone
Problems

Reactive Data Synchronization with withLatestFrom in Angular

withLatestFrom is a powerful operator in RxJS that allows you to combine the latest values from multiple Observables. This challenge focuses on implementing a scenario where you need to display a product's details alongside a dynamically updated discount percentage, demonstrating how withLatestFrom can synchronize data from different sources within an Angular component. Understanding this pattern is crucial for building reactive and responsive user interfaces.

Problem Description

You are building an Angular component that displays product information. The product details (name, description, price) are fetched from one Observable (product$). A separate Observable (discountPercentage$) emits the latest discount percentage, which is updated periodically (e.g., due to promotions). You need to display both the product details and the current discount percentage on the screen. The discount percentage should be applied to the product's price to calculate and display the discounted price.

Your task is to implement the Angular component using withLatestFrom to combine the latest values from product$ and discountPercentage$. The component should display the product name, description, original price, and the discounted price. When either the product details or the discount percentage changes, the displayed information should update accordingly.

Key Requirements:

  • Fetch product details from an Observable named product$. This Observable will emit an object with name, description, and price properties.
  • Fetch discount percentage from an Observable named discountPercentage$. This Observable will emit a number representing the discount percentage (e.g., 0.1 for 10%).
  • Use withLatestFrom to combine the latest values from product$ and discountPercentage$.
  • Calculate the discounted price by applying the discount percentage to the product's price.
  • Display the product name, description, original price, and discounted price in the component's template.
  • Handle the case where either product$ or discountPercentage$ is initially empty (no data).

Expected Behavior:

  • Initially, the component should display a loading indicator or a message indicating that the data is being fetched.
  • Once both product$ and discountPercentage$ emit values, the component should display the product details and the discounted price.
  • Whenever product$ emits a new product, the component should update the displayed product details and recalculate the discounted price.
  • Whenever discountPercentage$ emits a new discount percentage, the component should recalculate the discounted price and update the display.
  • If either Observable emits an error, the component should display an error message.

Examples

Example 1:

product$ = of({ name: 'Laptop', description: 'Powerful laptop for work and play', price: 1200 });
discountPercentage$ = of(0.1); // 10% discount

Output:
Product Name: Laptop
Description: Powerful laptop for work and play
Original Price: $1200
Discounted Price: $1080

Explanation: The product price is reduced by 10%, resulting in a discounted price of $1080.

Example 2:

product$ = of({ name: 'Smartphone', description: 'Latest smartphone model', price: 800 });
discountPercentage$ = of(0.25); // 25% discount

Output:
Product Name: Smartphone
Description: Latest smartphone model
Original Price: $800
Discounted Price: $600

Explanation: The product price is reduced by 25%, resulting in a discounted price of $600.

Example 3: (Edge Case - Initial Empty Values)

product$ = of({ name: 'Tablet', description: 'Portable tablet device', price: 300 }).pipe(delay(2000)); // Delayed emission
discountPercentage$ = of(0.05); // 5% discount

Output (Initially):
Loading...

Output (After 2 seconds):
Product Name: Tablet
Description: Portable tablet device
Original Price: $300
Discounted Price: $285

Explanation: The component initially displays "Loading..." because product$ is delayed. After 2 seconds, the product details and discounted price are displayed.

Constraints

  • The product$ Observable should emit an object with name (string), description (string), and price (number) properties.
  • The discountPercentage$ Observable should emit a number representing the discount percentage (between 0 and 1).
  • The component should be implemented using Angular's reactive forms or template-driven forms (though forms are not strictly required for this problem).
  • The component should handle potential errors from either Observable gracefully.
  • The solution should be concise and readable.

Notes

  • Consider using the async pipe in your template to subscribe to the combined Observable.
  • Think about how to handle the initial state where either product$ or discountPercentage$ might not have emitted a value yet. A loading indicator or placeholder content is a good approach.
  • withLatestFrom only emits when both Observables have emitted at least one value. This is important to remember when dealing with initial states.
  • You can use of to simulate Observables for testing purposes. In a real application, you would fetch data from an API or other data source.
Loading editor...
typescript