Issue
I'm trying to use Angular Material tables to list some infos I get from a backend server using websocket but it only shows the element when I click on the displayedColumns for sorting and not on initial load,
Here is my code for data table component:
import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTable } from '@angular/material/table';
import { observable, of as observableOf } from 'rxjs';
import { Observable } from 'rxjs/internal/Observable';
import { FtpClientComponent } from '../ftp-client/ftp-client.component';
import { FtpClientWsService } from '../services/ftp/ftp-client-ws.service';
import { DataTableDataSource, DataTableItem } from './data-table-datasource';
@Component({
selector: 'app-data-table',
templateUrl: './data-table.component.html',
styleUrls: ['./data-table.component.css']
})
export class DataTableComponent implements AfterViewInit{
@ViewChild(MatPaginator) paginator!: MatPaginator;
@ViewChild(MatSort) sort!: MatSort;
@ViewChild(MatTable) table!: MatTable<DataTableItem>;
dataSource: DataTableDataSource;
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['sftpName', 'sftpCreationDate'];
constructor(data:FtpClientComponent) {
this.dataSource = new DataTableDataSource(data);
}
ngAfterViewInit(): void {
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
this.table.dataSource = this.dataSource;
}
}
here is the datasource typescript:
import { DataSource } from '@angular/cdk/collections';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { map } from 'rxjs/operators';
import { Observable, of as observableOf, merge } from 'rxjs';
import { FtpClientComponent } from '../ftp-client/ftp-client.component';
// TODO: Replace this with your own data model type
export interface DataTableItem {
sftpName: string;
sftpCreationDate: string;
sftpPassword: string;
sftpUsedSpace: string;
sftpAllocatedSpace: string;
sftpLastModification: string;
}
// TODO: replace this with real data from your application
// const EXAMPLE_DATA: any[] = [];
/**
* Data source for the DataTable view. This class should
* encapsulate all logic for fetching and manipulating the displayed data
* (including sorting, pagination, and filtering).
*/
export class DataTableDataSource extends DataSource<DataTableItem> {
data: any[];
paginator: MatPaginator | undefined;
sort: MatSort | undefined;
constructor(data:FtpClientComponent) {
super();
this.data = data.receivedSftps
}
/**
* Connect this data source to the table. The table will only update when
* the returned stream emits new items.
* @returns A stream of the items to be rendered.
*/
connect(): Observable<DataTableItem[]> {
if (this.paginator && this.sort) {
// Combine everything that affects the rendered data into one update
// stream for the data-table to consume.
return merge(observableOf(this.data), this.paginator.page, this.sort.sortChange)
.pipe(map(() => {
return this.getPagedData(this.getSortedData([...this.data ]));
}));
} else {
throw Error('Please set the paginator and sort on the data source before connecting.');
}
}
/**
* Called when the table is being destroyed. Use this function, to clean up
* any open connections or free any held resources that were set up during connect.
*/
disconnect(): void {}
/**
* Paginate the data (client-side). If you're using server-side pagination,
* this would be replaced by requesting the appropriate data from the server.
*/
private getPagedData(data: DataTableItem[]): DataTableItem[] {
if (this.paginator) {
const startIndex = this.paginator.pageIndex * this.paginator.pageSize;
return data.splice(startIndex, this.paginator.pageSize);
} else {
return data;
}
}
/**
* Sort the data (client-side). If you're using server-side sorting,
* this would be replaced by requesting the appropriate data from the server.
*/
private getSortedData(data: DataTableItem[]): DataTableItem[] {
if (!this.sort || !this.sort.active || this.sort.direction === '') {
return data;
}
return data.sort((a, b) => {
const isAsc = this.sort?.direction === 'asc';
switch (this.sort?.active) {
case 'sftpName': return compare(a.sftpName, b.sftpName, isAsc);
case 'sftpCreationDate': return compare(+a.sftpName, +b.sftpName, isAsc);
default: return 0;
}
});
}
}
/** Simple sort comparator for example ID/Name columns (for client-side sorting). */
function compare(a: string | number, b: string | number, isAsc: boolean): number {
return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}
And the ftp-client component just uses a service that opens a websocket connection to retreive data that are then stored in a list
import { Component, OnInit } from '@angular/core';
import { FtpClientWsService } from '../services/ftp/ftp-client-ws.service';
@Component({
selector: 'app-ftp-client',
templateUrl: './ftp-client.component.html',
styleUrls: ['./ftp-client.component.css']
})
export class FtpClientComponent implements OnInit {
constructor(
public SftpWsService: FtpClientWsService
) { }
ngOnInit(): void {
this.SftpWsService.openWebSocket();
}
receivedSftps = this.SftpWsService.sftps;
}
The list appears only when I click on the sort headers, I'm new to Angular so any feedbacks are very welcome
Solution
adding a subcription on ngOninit() to the Subject in service before setting the datasource value solved the issue
Answered By - Mousse
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.