Implement Dynamic Pagination in an Angular Component
This challenge requires you to build a reusable Angular component that handles pagination for a list of items. Effective pagination is crucial for improving user experience when dealing with large datasets, allowing users to navigate through information without overwhelming them.
Problem Description
Your task is to create an Angular component, PaginationComponent, that displays pagination controls for a given total number of items and a specified number of items per page. This component should:
- Display Page Numbers: Show a series of clickable page numbers.
- Navigate Pages: Allow users to click on page numbers to select a different page.
- Indicate Current Page: Visually highlight the currently active page.
- Control Items Per Page: Potentially offer a way (though not strictly required for the core challenge) for users to change the number of items displayed per page. For this challenge, assume a fixed
itemsPerPageis provided. - Handle First/Last/Previous/Next Navigation: Include buttons for navigating to the first page, previous page, next page, and last page.
- Manage Total Pages: Dynamically calculate the total number of pages based on the
totalItemsanditemsPerPage. - Emit Page Change Events: Notify the parent component when the user selects a new page, providing the newly selected page number.
Key Requirements:
- Component Structure: Create a standalone Angular component (
PaginationComponent). - Inputs: The component should accept the following inputs:
totalItems: Anumberrepresenting the total count of items to be paginated.itemsPerPage: Anumberrepresenting how many items should be displayed on each page.currentPage: Anumberrepresenting the currently active page (zero-based or one-based, be consistent and document it). Let's assume one-based for this challenge.
- Outputs: The component should emit an output event:
pageChanged: AnEventEmitter<number>that emits the new page number whenever the user navigates to a different page.
- Behavior:
- Calculate
totalPagesasMath.ceil(totalItems / itemsPerPage). - Render page numbers from 1 up to
totalPages. - The "Previous" button should be disabled if
currentPageis 1. - The "Next" button should be disabled if
currentPageis equal tototalPages. - The "First" button should be disabled if
currentPageis 1. - The "Last" button should be disabled if
currentPageis equal tototalPages. - The currently selected page number should have a distinct visual style (e.g., a different background color or font weight).
- Calculate
- Edge Cases:
totalItemsis 0.itemsPerPageis 0 (or invalid). Handle gracefully, perhaps by displaying no pagination or an error. AssumeitemsPerPagewill be a positive integer for this challenge.totalItemsis less thanitemsPerPage.- A large number of
totalPagesmight require "ellipsis" (...) to represent omitted page numbers, though for this challenge, displaying all page numbers is sufficient iftotalPagesis reasonably small (e.g., <= 10).
Examples
Example 1:
Input to PaginationComponent:
@Input() totalItems = 100;
@Input() itemsPerPage = 10;
@Input() currentPage = 1;
Expected UI Output (Simplified representation):
First | Prev | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Next | Last
(Page 1 is highlighted)
Example 2:
Input to PaginationComponent:
@Input() totalItems = 35;
@Input() itemsPerPage = 5;
@Input() currentPage = 4;
Expected UI Output (Simplified representation):
First | Prev | 1 | 2 | 3 | 4 | 5 | 6 | 7 | Next | Last
(Page 4 is highlighted)
Example 3: Edge Case - No items
Input to PaginationComponent:
@Input() totalItems = 0;
@Input() itemsPerPage = 10;
@Input() currentPage = 1;
Expected UI Output:
(No pagination controls displayed)
Example 4: Edge Case - All items on one page
Input to PaginationComponent:
@Input() totalItems = 8;
@Input() itemsPerPage = 10;
@Input() currentPage = 1;
Expected UI Output (Simplified representation):
First | Prev | 1 | Next | Last
(Page 1 is highlighted)
Constraints
- The pagination component must be implemented using Angular (version 12+ recommended).
- Use TypeScript for the component logic.
- The styling for the pagination controls can be basic CSS, but it should clearly indicate the current page.
- The
currentPageinput will always be a valid page number between 1 andtotalPages(inclusive), or 1 iftotalItemsis 0. totalItemsanditemsPerPagewill be non-negative integers.- Assume a reasonable maximum number of
totalPages(e.g., <= 20) for simplicity in displaying page numbers; you don't need to implement complex ellipsis for this core challenge.
Notes
- Consider how you will generate the list of page numbers to display. A simple
*ngForloop is a good starting point. - Think about the logic for handling clicks on page numbers, "First," "Prev," "Next," and "Last" buttons. Ensure these actions correctly update the
currentPageand emit thepageChangedevent. - Remember to handle the
disabledstate of navigation buttons based on thecurrentPageandtotalPages. - You'll need to define CSS classes or styles to visually distinguish the active page.
- Consider the zero-based vs. one-based indexing for
currentPage. For this challenge, we've specified one-based. Ensure your internal logic and emitted values are consistent.