Angular Router Module Implementation
This challenge asks you to implement a simplified version of Angular's RouterModule. The goal is to understand the core concepts of routing – defining routes, navigating between them, and handling route parameters – without relying on the full Angular framework. This exercise will solidify your understanding of how routing works under the hood.
Problem Description
You are tasked with creating a RouterModule class that manages navigation between different "pages" (represented as simple components). The router should allow you to:
- Define Routes: Routes are objects with a
path(string) and acomponent(a function that returns a string representing the HTML for that page). - Navigate: A
navigatemethod should take a path (string) as input and render the corresponding component's HTML. - Route Parameters: The
pathcan include parameters enclosed in curly braces (e.g.,/user/:id). Thenavigatemethod should extract these parameters and pass them to the component function. - Error Handling: If the provided path doesn't match any defined routes, a default "Not Found" component should be rendered.
Key Requirements:
- The
RouterModuleclass should be able to store and retrieve routes. - The
navigatemethod should parse the path, extract parameters (if any), and call the appropriate component function. - The component functions should receive a
paramsobject containing the extracted route parameters. - The
RouterModuleshould handle cases where a route doesn't exist.
Expected Behavior:
When navigate is called with a valid path, the component associated with that path should be executed, and its returned HTML should be rendered. Route parameters should be correctly passed to the component. If the path is invalid, the "Not Found" component should be rendered.
Edge Cases to Consider:
- Paths with no parameters.
- Paths with multiple parameters.
- Invalid paths (paths that don't match any defined routes).
- Empty paths.
- Component functions that don't accept a
paramsargument.
Examples
Example 1:
Input:
routes = [
{ path: '/', component: () => '<h1>Home Page</h1>' },
{ path: '/about', component: () => '<h1>About Page</h1>' }
];
router = new RouterModule(routes);
router.navigate('/');
Output:
<h1>Home Page</h1>
Explanation: The path '/' matches the first route. The component function is executed, and its returned HTML is rendered.
Example 2:
Input:
routes = [
{ path: '/user/:id', component: (params) => `<h1>User ID: ${params.id}</h1>` }
];
router = new RouterModule(routes);
router.navigate('/user/123');
Output:
<h1>User ID: 123</h1>
Explanation: The path '/user/123' matches the route with the parameter ':id'. The component function is executed with params = { id: '123' }.
Example 3:
Input:
routes = [
{ path: '/', component: () => '<h1>Home Page</h1>' }
];
router = new RouterModule(routes);
router.navigate('/nonexistent');
Output:
<h1>404 Not Found</h1>
Explanation: The path '/nonexistent' doesn't match any defined routes. The default "Not Found" component is rendered.
Constraints
- The
pathstrings should be simple strings without complex regular expressions. - Route parameters should be extracted as strings.
- Component functions should be synchronous and return a string representing the HTML.
- The
RouterModuleclass should be relatively lightweight and easy to understand. - Performance is not a primary concern for this exercise; focus on correctness and clarity.
Notes
- You don't need to create a full-fledged router with features like route guards or lazy loading.
- Focus on the core functionality of defining routes, navigating between them, and handling route parameters.
- Consider using regular expressions to parse the path and extract parameters. However, keep the regex simple for clarity.
- The "Not Found" component can be a simple function that returns "<h1>404 Not Found</h1>".
- Think about how to handle cases where a component function doesn't expect a
paramsargument. You might choose to ignore it or throw an error. Document your choice. - The
RouterModuleclass should be designed to be extensible, allowing for easy addition of new routes.