Skip to content

Commit de23a27

Browse files
committed
page count grid refresh update
1 parent f6688cc commit de23a27

File tree

2 files changed

+100
-8
lines changed

2 files changed

+100
-8
lines changed

frontend/src/app/feature/contact/contact-list/contact-list.component.html

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ <h1 class="text-2xl font-bold">Contacts</h1>
2222

2323
<!-- Table Container -->
2424
<div class="max-w-6xl mx-auto bg-surface-container rounded-lg shadow-lg overflow-x-auto transition-all duration-300">
25-
<table mat-table [dataSource]="dataSource()" matSort class="min-w-full">
25+
<table mat-table [dataSource]="dataSource()" matSort (matSortChange)="sortData($event)" class="min-w-full">
2626
<!-- Name Column -->
2727
<ng-container matColumnDef="name">
2828
<th mat-header-cell *matHeaderCellDef mat-sort-header class="bg-surface-container-high font-medium text-on-surface-variant px-6 py-4 w-[20%]">Name</th>
@@ -84,5 +84,15 @@ <h1 class="text-2xl font-bold">Contacts</h1>
8484
</td>
8585
</tr>
8686
</table>
87+
88+
<!-- Paginator -->
89+
<mat-paginator
90+
[pageSize]="pageSize()"
91+
[pageSizeOptions]="pageSizeOptions"
92+
[length]="totalItems()"
93+
(page)="pageChanged($event)"
94+
class="border-t border-outline-variant"
95+
aria-label="Select page of contacts">
96+
</mat-paginator>
8797
</div>
8898
</div>

frontend/src/app/feature/contact/contact-list/contact-list.component.ts

Lines changed: 89 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import { DecimalPipe, CommonModule } from '@angular/common';
2-
import { Component, ViewChild, OnInit, inject, signal } from '@angular/core';
3-
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
2+
import { Component, ViewChild, OnInit, inject, signal, computed, AfterViewInit } from '@angular/core';
3+
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
44
import { Router, RouterModule } from '@angular/router';
5-
import { MatPaginatorModule } from '@angular/material/paginator';
5+
import { MatPaginator, MatPaginatorModule, PageEvent } from '@angular/material/paginator';
66
import { MatFormFieldModule } from '@angular/material/form-field';
77
import { MatInputModule } from '@angular/material/input';
88
import { MatTableModule } from '@angular/material/table';
99
import { MatIconModule } from '@angular/material/icon';
1010
import { MatButtonModule } from '@angular/material/button';
1111
import { MatTooltipModule } from '@angular/material/tooltip';
12-
import { MatSort, MatSortModule } from '@angular/material/sort';
12+
import { MatSort, MatSortModule, Sort } from '@angular/material/sort';
1313
import { MatTableDataSource } from '@angular/material/table';
1414
import { ContactService } from '@features/contact/contact.service';
1515
import { HasPermissionDirective } from '@core/directives/permission.directive';
@@ -37,22 +37,38 @@ import { NotificationService } from '@core/services/notification.service';
3737
styleUrl: './contact-list.component.scss',
3838
providers: [DecimalPipe, ContactService]
3939
})
40-
export class ContactListComponent implements OnInit {
40+
export class ContactListComponent implements OnInit, AfterViewInit {
4141
private contactService = inject(ContactService);
4242
private router = inject(Router);
4343
private notificationService = inject(NotificationService);
4444

4545
contacts = signal<any[]>([]);
46+
filteredContacts = signal<any[]>([]);
4647
dataSource = signal<MatTableDataSource<any>>(new MatTableDataSource([]));
4748
displayedColumns = ['name', 'email', 'phone', 'city', 'actions'];
4849
loading = signal<boolean>(false);
4950

51+
// Pagination related signals
52+
pageSize = signal<number>(10);
53+
currentPage = signal<number>(0);
54+
pageSizeOptions = [5, 10, 25, 50];
55+
totalItems = computed(() => this.filteredContacts().length);
56+
5057
@ViewChild(MatSort) sort!: MatSort;
58+
@ViewChild(MatPaginator) paginator!: MatPaginator;
5159

5260
ngOnInit(): void {
5361
this.loadContacts();
5462
}
5563

64+
ngAfterViewInit() {
65+
// Connect the sort and paginator after the view is initialized
66+
if (this.dataSource()) {
67+
this.dataSource().sort = this.sort;
68+
this.dataSource().paginator = this.paginator;
69+
}
70+
}
71+
5672
loadContacts(): void {
5773
this.loading.set(true);
5874
this.contactService.getAll().subscribe({
@@ -61,8 +77,19 @@ export class ContactListComponent implements OnInit {
6177
new Date(b.create_date).getTime() - new Date(a.create_date).getTime()
6278
);
6379
this.contacts.set(sortedData);
64-
this.dataSource.set(new MatTableDataSource(sortedData));
65-
this.dataSource().sort = this.sort;
80+
this.filteredContacts.set(sortedData);
81+
82+
const dataSource = new MatTableDataSource(sortedData);
83+
this.dataSource.set(dataSource);
84+
85+
// Initialize sort and paginator if they're available
86+
if (this.sort) {
87+
dataSource.sort = this.sort;
88+
}
89+
if (this.paginator) {
90+
dataSource.paginator = this.paginator;
91+
}
92+
6693
this.loading.set(false);
6794
},
6895
error: (error) => {
@@ -75,6 +102,61 @@ export class ContactListComponent implements OnInit {
75102
applyFilter(event: Event) {
76103
const filterValue = (event.target as HTMLInputElement).value;
77104
this.dataSource().filter = filterValue.trim().toLowerCase();
105+
106+
// Reset to first page when filtering
107+
if (this.dataSource().paginator) {
108+
this.dataSource().paginator.firstPage();
109+
}
110+
}
111+
112+
pageChanged(event: PageEvent): void {
113+
this.pageSize.set(event.pageSize);
114+
this.currentPage.set(event.pageIndex);
115+
116+
// Update the data source's pagination parameters
117+
if (this.dataSource()) {
118+
// This ensures the MatTableDataSource is aware of the new page size
119+
this.dataSource().paginator = this.paginator;
120+
121+
// Force the data source to reflect changes by resetting its data
122+
// This is important when items per page changes
123+
const currentData = this.dataSource().data;
124+
this.dataSource().data = [...currentData];
125+
}
126+
}
127+
128+
sortData(sort: Sort): void {
129+
if (!sort.active || sort.direction === '') {
130+
// If sorting is cleared, revert to original data
131+
this.dataSource().data = this.filteredContacts();
132+
return;
133+
}
134+
135+
this.dataSource().data = [...this.filteredContacts()].sort((a, b) => {
136+
const isAsc = sort.direction === 'asc';
137+
switch (sort.active) {
138+
case 'name':
139+
return this.compareNames(a, b, isAsc);
140+
case 'email':
141+
return this.compare(a.email, b.email, isAsc);
142+
case 'phone':
143+
return this.compare(a.mobile, b.mobile, isAsc);
144+
case 'city':
145+
return this.compare(a.city, b.city, isAsc);
146+
default:
147+
return 0;
148+
}
149+
});
150+
}
151+
152+
compareNames(a: any, b: any, isAsc: boolean): number {
153+
const nameA = `${a.firstName} ${a.lastName}`.toLowerCase();
154+
const nameB = `${b.firstName} ${b.lastName}`.toLowerCase();
155+
return (nameA < nameB ? -1 : 1) * (isAsc ? 1 : -1);
156+
}
157+
158+
compare(a: string | number, b: string | number, isAsc: boolean): number {
159+
return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
78160
}
79161

80162
deleteContact(contact: any): void {

0 commit comments

Comments
 (0)