Angular Search Bar: Real-time Filtering of a Product List
This challenge focuses on implementing a dynamic search bar component in Angular that filters a list of products in real-time as the user types. This is a fundamental feature for many e-commerce and data-driven applications, enhancing user experience by allowing quick access to desired items.
Problem Description
You are tasked with building an Angular component that displays a list of products and provides a search bar to filter these products based on their names. The filtering should be case-insensitive and update the displayed list instantly as the user types.
Key Requirements:
- Product Display: A component should display a list of products. Each product should have at least an
idand aname. - Search Input: Implement an input field (search bar) where users can type their search queries.
- Real-time Filtering: As the user types into the search bar, the product list should dynamically update to show only products whose names contain the entered search term.
- Case-Insensitive Search: The search functionality should ignore the case of both the search term and the product names.
- "No Results" Message: If no products match the search query, a clear message (e.g., "No products found") should be displayed instead of an empty list.
- Initial State: When the component loads, all products should be visible.
Expected Behavior:
- When the page loads, the full list of products is displayed.
- As the user types characters into the search bar, the list shrinks to show only matching products.
- If the user deletes characters, the list expands accordingly.
- If the search bar is empty, all products are displayed.
Edge Cases:
- Empty Search Term: The search bar is empty.
- No Matching Products: The user enters a term that does not match any product names.
- Special Characters: Consider how the search should behave with special characters in product names or search terms (though for this challenge, assume basic alphanumeric characters).
Examples
Example 1:
Initial State:
- Products:
{ id: 1, name: 'Laptop' }{ id: 2, name: 'Keyboard' }{ id: 3, name: 'Mouse' }{ id: 4, name: 'Monitor' }
- Search Input: (empty)
- Displayed Product List:
LaptopKeyboardMouseMonitor
User types "lap":
- Search Input:
lap - Displayed Product List:
Laptop
Explanation: The list is filtered to show only products whose names contain "lap" (case-insensitive).
Example 2:
State:
- Products:
{ id: 1, name: 'Apple' }{ id: 2, name: 'Banana' }{ id: 3, name: 'Apricot' }{ id: 4, name: 'Orange' }
- Search Input:
a - Displayed Product List:
AppleBananaApricot
User types "app":
- Search Input:
app - Displayed Product List:
Apple
Explanation: The filter is refined. "Banana" and "Apricot" are removed because they don't contain "app".
Example 3 (Edge Case):
State:
- Products:
{ id: 1, name: 'Table' }{ id: 2, name: 'Chair' }{ id: 3, name: 'Lamp' }
- Search Input:
xyz - Displayed Product List:
No products found
Explanation: The search term "xyz" matches no product names, so the "No products found" message is displayed.
Constraints
- You will be provided with an array of product objects, each having at least
id(number) andname(string) properties. - The filtering logic should be efficient enough to provide near-instantaneous updates for a moderate number of products (e.g., up to 1000).
- The solution must be implemented using TypeScript within an Angular project structure.
- Avoid using external libraries for the search functionality itself (e.g., pre-built search components).
Notes
- Consider using Angular's
OnPushchange detection strategy for performance optimization if dealing with a very large number of products or frequent updates. - Think about how to handle the input changes. RxJS operators like
debounceTimeanddistinctUntilChangedcan be very useful here to avoid excessive filtering operations while the user is still typing. - Structure your component with clear separation of concerns: data retrieval/mocking, filtering logic, and template rendering.
- You can simulate data fetching by creating a static array of products within your component or service.