Last active
July 6, 2022 11:22
-
-
Save jhades/9cdcff38c5f5092069363ddf69bda5bf to your computer and use it in GitHub Desktop.
Angular Material Data Table blog post - https://blog.angular-university.io/angular-material-data-table
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { MatInputModule, MatPaginatorModule, MatProgressSpinnerModule, | |
MatSortModule, MatTableModule } from "@angular/material"; | |
@NgModule({ | |
declarations: [ | |
... | |
], | |
imports: [ | |
BrowserModule, | |
BrowserAnimationsModule, | |
HttpClientModule, | |
MatInputModule, | |
MatTableModule, | |
MatPaginatorModule, | |
MatSortModule, | |
MatProgressSpinnerModule | |
], | |
providers: [ | |
... | |
], | |
bootstrap: [AppComponent] | |
}) | |
export class AppModule { | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<mat-table class="lessons-table mat-elevation-z8" [dataSource]="dataSource"> | |
<ng-container matColumnDef="seqNo"> | |
<div *matHeaderCellDef>#</div> | |
<div *matCellDef="let lesson">{{lesson.seqNo}}</div> | |
</ng-container> | |
<ng-container matColumnDef="description"> | |
<div *matHeaderCellDef>Description</div> | |
<div class="description-cell" | |
*matCellDef="let lesson">{{lesson.description}}</div> | |
</ng-container> | |
<ng-container matColumnDef="duration"> | |
<div *matHeaderCellDef>Duration</div> | |
<div class="duration-cell" | |
*matCellDef="let lesson">{{lesson.duration}}</div> | |
</ng-container> | |
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row> | |
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row> | |
</mat-table> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<mat-table class="lessons-table mat-elevation-z8" [dataSource]="dataSource"> | |
<ng-container matColumnDef="seqNo"> | |
<mat-header-cell *matHeaderCellDef>#</mat-header-cell> | |
<mat-cell *matCellDef="let lesson">{{lesson.seqNo}}</mat-cell> | |
</ng-container> | |
<ng-container matColumnDef="description"> | |
<mat-header-cell *matHeaderCellDef>Description</mat-header-cell> | |
<mat-cell class="description-cell" | |
*matCellDef="let lesson">{{lesson.description}}</mat-cell> | |
</ng-container> | |
<ng-container matColumnDef="duration"> | |
<mat-header-cell *matHeaderCellDef>Duration</mat-header-cell> | |
<mat-cell class="duration-cell" | |
*matCellDef="let lesson">{{lesson.duration}}</mat-cell> | |
</ng-container> | |
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row> | |
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row> | |
</mat-table> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
displayedColumns = ["seqNo", "description", "duration"]; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<mat-row *matRowDef="let row; columns: displayedColumns" | |
(click)="onRowClicked(row)"> | |
</mat-row> | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
onRowClicked(row) { | |
console.log('Row clicked: ', row); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Injectable() | |
export class CoursesService { | |
constructor(private http:HttpClient) {} | |
findLessons( | |
courseId:number, filter = '', sortOrder = 'asc', | |
pageNumber = 0, pageSize = 3): Observable<Lesson[]> { | |
return this.http.get('/api/lessons', { | |
params: new HttpParams() | |
.set('courseId', courseId.toString()) | |
.set('filter', filter) | |
.set('sortOrder', sortOrder) | |
.set('pageNumber', pageNumber.toString()) | |
.set('pageSize', pageSize.toString()) | |
}).pipe( | |
map(res => res["payload"]) | |
); | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {CollectionViewer, DataSource} from "@angular/cdk/collections"; | |
export class LessonsDataSource implements DataSource<Lesson> { | |
private lessonsSubject = new BehaviorSubject<Lesson[]>([]); | |
constructor(private coursesService: CoursesService) {} | |
connect(collectionViewer: CollectionViewer): Observable<Lesson[]> { | |
... | |
} | |
disconnect(collectionViewer: CollectionViewer): void { | |
... | |
} | |
loadLessons(courseId: number, filter: string, | |
sortDirection: string, pageIndex: number, pageSize: number) { | |
... | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export class LessonsDataSource implements DataSource<Lesson> { | |
private lessonsSubject = new BehaviorSubject<Lesson[]>([]); | |
private loadingSubject = new BehaviorSubject<boolean>(false); | |
public loading$ = this.loadingSubject.asObservable(); | |
constructor(private coursesService: CoursesService) {} | |
connect(collectionViewer: CollectionViewer): Observable<Lesson[]> { | |
return this.lessonsSubject.asObservable(); | |
} | |
disconnect(collectionViewer: CollectionViewer): void { | |
this.lessonsSubject.complete(); | |
this.loadingSubject.complete(); | |
} | |
loadLessons(courseId: number, filter = '', | |
sortDirection = 'asc', pageIndex = 0, pageSize = 3) { | |
this.loadingSubject.next(true); | |
this.coursesService.findLessons(courseId, filter, sortDirection, | |
pageIndex, pageSize).pipe( | |
catchError(() => of([])), | |
finalize(() => this.loadingSubject.next(false)) | |
) | |
.subscribe(lessons => this.lessonsSubject.next(lessons)); | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Component({ | |
selector: 'course', | |
templateUrl: './course.component.html', | |
styleUrls: ['./course.component.css'] | |
}) | |
export class CourseComponent implements OnInit { | |
dataSource: LessonsDataSource; | |
displayedColumns= ["seqNo", "description", "duration"]; | |
constructor(private coursesService: CoursesService) {} | |
ngOnInit() { | |
this.dataSource = new LessonsDataSource(this.coursesService); | |
this.dataSource.loadLessons(1); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="course"> | |
<div class="spinner-container" *ngIf="dataSource.loading$ | async"> | |
<mat-spinner></mat-spinner> | |
</div> | |
<mat-table class="lessons-table mat-elevation-z8" [dataSource]="dataSource"> | |
.... | |
</mat-table> | |
</div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="course"> | |
<div class="spinner-container" *ngIf="dataSource.loading$ | async"> | |
<mat-spinner></mat-spinner> | |
</div> | |
<mat-table class="lessons-table mat-elevation-z8" [dataSource]="dataSource"> | |
.... | |
</mat-table> | |
<mat-paginator [length]="course?.lessonsCount" [pageSize]="3" | |
[pageSizeOptions]="[3, 5, 10]"></mat-paginator> | |
</div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Component({ | |
selector: 'course', | |
templateUrl: './course.component.html', | |
styleUrls: ['./course.component.css'] | |
}) | |
export class CourseComponent implements AfterViewInit, OnInit { | |
course:Course; | |
dataSource: LessonsDataSource; | |
displayedColumns= ["seqNo", "description", "duration"]; | |
@ViewChild(MatPaginator) paginator: MatPaginator; | |
constructor(private coursesService: CoursesService, private route: ActivatedRoute) {} | |
ngOnInit() { | |
this.course = this.route.snapshot.data["course"]; | |
this.dataSource = new LessonsDataSource(this.coursesService); | |
this.dataSource.loadLessons(this.course.id, '', 'asc', 0, 3); | |
} | |
ngAfterViewInit() { | |
this.paginator.page | |
.pipe( | |
tap(() => this.loadLessonsPage()) | |
) | |
.subscribe(); | |
} | |
loadLessonsPage() { | |
this.dataSource.loadLessons( | |
this.course.id, | |
'', | |
'asc', | |
this.paginator.pageIndex, | |
this.paginator.pageSize); | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<mat-table class="lessons-table mat-elevation-z8" [dataSource]="dataSource" | |
matSort matSortActive="seqNo" matSortDirection="asc" matSortDisableClear> | |
<ng-container matColumnDef="seqNo"> | |
<mat-header-cell *matHeaderCellDef mat-sort-header>#</mat-header-cell> | |
<mat-cell *matCellDef="let lesson">{{lesson.seqNo}}</mat-cell> | |
</ng-container> | |
.... | |
</mat-table> | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Component({ | |
selector: 'course', | |
templateUrl: './course.component.html', | |
styleUrls: ['./course.component.css'] | |
}) | |
export class CourseComponent implements AfterViewInit, OnInit { | |
course:Course; | |
dataSource: LessonsDataSource; | |
displayedColumns= ["seqNo", "description", "duration"]; | |
@ViewChild(MatPaginator) paginator: MatPaginator; | |
@ViewChild(MatSort) sort: MatSort; | |
constructor(private coursesService: CoursesService, private route: ActivatedRoute) {} | |
ngOnInit() { | |
this.course = this.route.snapshot.data["course"]; | |
this.dataSource = new LessonsDataSource(this.coursesService); | |
this.dataSource.loadLessons(this.course.id, '', 'asc', 0, 3); | |
} | |
ngAfterViewInit() { | |
// reset the paginator after sorting | |
this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0); | |
merge(this.sort.sortChange, this.paginator.page) | |
.pipe( | |
tap(() => this.loadLessonsPage()) | |
) | |
.subscribe(); | |
} | |
loadLessonsPage() { | |
this.dataSource.loadLessons( | |
this.course.id, '', this.sort.direction, | |
this.paginator.pageIndex, this.paginator.pageSize); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="course"> | |
<!-- New part: this is the search box --> | |
<mat-input-container> | |
<input matInput placeholder="Search lessons" #input> | |
</mat-input-container> | |
<div class="spinner-container" *ngIf="dataSource.loading$ | async"> | |
<mat-spinner></mat-spinner> | |
</div> | |
<mat-table class="lessons-table mat-elevation-z8" [dataSource]="dataSource" | |
matSort matSortActive="seqNo" matSortDirection="asc" matSortDisableClear> | |
<ng-container matColumnDef="seqNo"> | |
<mat-header-cell *matHeaderCellDef mat-sort-header>#</mat-header-cell> | |
<mat-cell *matCellDef="let lesson">{{lesson.seqNo}}</mat-cell> | |
</ng-container> | |
<ng-container matColumnDef="description"> | |
<mat-header-cell *matHeaderCellDef>Description</mat-header-cell> | |
<mat-cell class="description-cell" | |
*matCellDef="let lesson">{{lesson.description}}</mat-cell> | |
</ng-container> | |
<ng-container matColumnDef="duration"> | |
<mat-header-cell *matHeaderCellDef>Duration</mat-header-cell> | |
<mat-cell class="duration-cell" | |
*matCellDef="let lesson">{{lesson.duration}}</mat-cell> | |
</ng-container> | |
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row> | |
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row> | |
</mat-table> | |
<mat-paginator [length]="course?.lessonsCount" [pageSize]="3" | |
[pageSizeOptions]="[3, 5, 10]"></mat-paginator> | |
</div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Component({ | |
selector: 'course', | |
templateUrl: './course.component.html', | |
styleUrls: ['./course.component.css'] | |
}) | |
export class CourseComponent implements OnInit, AfterViewInit { | |
course:Course; | |
dataSource: LessonsDataSource; | |
displayedColumns= ["seqNo", "description", "duration"]; | |
@ViewChild(MatPaginator) paginator: MatPaginator; | |
@ViewChild(MatSort) sort: MatSort; | |
@ViewChild('input') input: ElementRef; | |
constructor( | |
private route: ActivatedRoute, | |
private coursesService: CoursesService) {} | |
ngOnInit() { | |
this.course = this.route.snapshot.data["course"]; | |
this.dataSource = new LessonsDataSource(this.coursesService); | |
this.dataSource.loadLessons(this.course.id, '', 'asc', 0, 3); | |
} | |
ngAfterViewInit() { | |
// server-side search | |
fromEvent(this.input.nativeElement,'keyup') | |
.pipe( | |
debounceTime(150), | |
distinctUntilChanged(), | |
tap(() => { | |
this.paginator.pageIndex = 0; | |
this.loadLessonsPage(); | |
}) | |
) | |
.subscribe(); | |
// reset the paginator after sorting | |
this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0); | |
// on sort or paginate events, load a new page | |
merge(this.sort.sortChange, this.paginator.page) | |
.pipe( | |
tap(() => this.loadLessonsPage()) | |
) | |
.subscribe(); | |
} | |
loadLessonsPage() { | |
this.dataSource.loadLessons( | |
this.course.id, | |
this.input.nativeElement.value, | |
this.sort.direction, | |
this.paginator.pageIndex, | |
this.paginator.pageSize); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// server-side search | |
fromEvent(this.input.nativeElement,'keyup') | |
.pipe( | |
debounceTime(150), | |
distinctUntilChanged(), | |
tap(() => { | |
this.paginator.pageIndex = 0; | |
this.loadLessonsPage(); | |
}) | |
) | |
.subscribe(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
connect(collectionViewer: CollectionViewer): Observable<Lesson[]> { | |
return this.lessonsSubject.asObservable(); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
disconnect(collectionViewer: CollectionViewer): void { | |
this.lessonsSubject.complete(); | |
this.loadingSubject.complete(); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
loadLessons(courseId: number, filter = '', | |
sortDirection = 'asc', pageIndex = 0, pageSize = 3) { | |
this.loadingSubject.next(true); | |
this.coursesService.findLessons(courseId, filter, sortDirection, | |
pageIndex, pageSize).pipe( | |
catchError(() => of([])), | |
finalize(() => this.loadingSubject.next(false)) | |
) | |
.subscribe(lessons => this.lessonsSubject.next(lessons)); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ngAfterViewInit() { | |
this.paginator.page | |
.pipe( | |
tap(() => this.loadLessonsPage()) | |
) | |
.subscribe(); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="spinner-container" *ngIf="dataSource.loading$ | async"> | |
<mat-spinner></mat-spinner> | |
</div> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment