<!--Filtering input fields-->
<div class="example-header">
<mat-form-field>
<input matInput #filter placeholder="Αναζήτηση">
</mat-form-field>
</div>
<div class="example-container mat-elevation-z8">
<ng4-loading-spinner></ng4-loading-spinner>
<mat-table #table [dataSource]="incidentsDataSource" matSort>
<ng-container matColumnDef="protocolNo">
<mat-header-cell *matHeaderCellDef mat-sort-header> Αρ. Πρωτοκόλλου</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.protocolNo}}</mat-cell>
</ng-container>
<ng-container matColumnDef="date">
<mat-header-cell *matHeaderCellDef mat-sort-header> Ημερομηνία</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.date | date:'dd/MM/yyyy' }}</mat-cell>
</ng-container>
<ng-container matColumnDef="patient">
<mat-header-cell *matHeaderCellDef mat-sort-header> Ασθενής</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.patient.lastName}} {{row.patient.firstName}}</mat-cell>
</ng-container>
<ng-container matColumnDef="doctor">
<mat-header-cell *matHeaderCellDef mat-sort-header> Ιατρός</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.doctor.lastName}} {{row.doctor.firstName}}</mat-cell>
</ng-container>
<ng-container matColumnDef="signingDoctor">
<mat-header-cell *matHeaderCellDef mat-sort-header> Υπογράφων Ιατρός</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.signingDoctor.lastName}} {{row.signingDoctor.firstName}}</mat-cell>
</ng-container>
<ng-container matColumnDef="clinic">
<mat-header-cell *matHeaderCellDef mat-sort-header> Κλινική</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.clinic?.name}}</mat-cell>
</ng-container>
<ng-container matColumnDef="isPayed">
<mat-header-cell *matHeaderCellDef mat-sort-header> Πληρωμή</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.isPayed | payment}}</mat-cell>
</ng-container>
<ng-container matColumnDef="actions">
<mat-header-cell *matHeaderCellDef> Ενέργειες</mat-header-cell>
<mat-cell *matCellDef="let row" style="white-space: nowrap">
<button mat-icon-button (click)="openDialog(row)">
<span matTooltip="Λεπτομέρειες!">
<mat-icon style="color: grey">assignment</mat-icon>
</span>
</button>
<a [routerLink]="['./update', row.id]">
<span matTooltip="Επεξεργασία!">
<mat-icon>mode_edit</mat-icon>
</span>
</a>
<a [routerLink]="['./delete', row.id]">
<span matTooltip="Διαγραφή!">
<mat-icon>delete</mat-icon>
</span>
</a>
<button mat-icon-button (click)="renderPDF(row.id)">
<span matTooltip="Λεπτομέρειες!">
<mat-icon style="color: grey">picture_as_pdf</mat-icon>
</span>
</button>
<!--<a [routerLink]="['./pdf', row.id]">-->
<!--<span matTooltip="Προβολή PDF!">-->
<!--<mat-icon>picture_as_pdf</mat-icon>-->
<!--</span>-->
<!--</a>-->
</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 #paginator
[length]="incidentsDataSource?.filteredData.length"
[pageIndex]="0"
[pageSize]="25"
[pageSizeOptions]="[25, 50, 100, 250, 500]">
</mat-paginator>
</div>
incidents-list.component.ts
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {IncidentsService} from '../incidents.service';
import {Router} from '@angular/router';
import {MatDialog, MatPaginator, MatSort} from '@angular/material';
import {Incident} from '../incident';
import 'rxjs/add/observable/fromEvent';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import {Ng4LoadingSpinnerService} from 'ng4-loading-spinner';
import {IncidentsCommunicationService} from '../../shared/services/incidents-communication.service';
import {IncidentDetailsComponent} from '../incident-details/incident-details.component';
import {Observable} from 'rxjs/Observable';
import {IncidentsDataSource} from '../../shared/lib/incidents-data-source';
@Component({
selector: 'app-incidents-list',
templateUrl: './incidents-list.component.html',
styleUrls: ['./incidents-list.component.css']
})
export class IncidentsListComponent implements OnInit {
displayedColumns = ['protocolNo', 'date', 'patient', 'doctor', 'signingDoctor', 'clinic', 'isPayed', 'actions'];
incidentsDataSource: IncidentsDataSource | null;
// incidentsDataSource: MatTableDataSource<Incident>;
incidents: Incident[] = [];
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
@ViewChild('filter') filter: ElementRef;
constructor(private spinner: Ng4LoadingSpinnerService, private incidentsService: IncidentsService,
private router: Router, private comService: IncidentsCommunicationService, private dialog: MatDialog) {
}
async ngOnInit() {
this.incidentsDataSource = new IncidentsDataSource(this.comService, this.paginator, this.sort);
await this.getIncidents();
Observable.fromEvent(this.filter.nativeElement, 'keyup')
.debounceTime(150)
.distinctUntilChanged()
.subscribe(() => {
if (!this.incidentsDataSource) {
return;
}
this.incidentsDataSource.filter = this.filter.nativeElement.value;
});
}
getIncidents() {
this.spinner.show();
this.incidentsService.getIncidents().subscribe((results) => {
// console.log('allalalala: ' + JSON.stringify(results));
// this.incidentsDataSource.data = results;
this.comService.sendIncidents(results);
this.spinner.hide();
});
}
show(incidentID) {
this.router.navigate(['incidents/details/', incidentID]);
}
openDialog(incident: Incident) {
const dialogRef = this.dialog.open(IncidentDetailsComponent, {height: '700px', 'data': {'incident': incident}});
}
renderPDF(id: number) {
this.incidentsService.getPdfById(id)
.subscribe(response => {
console.log('Response: ' + response);
const file = new Blob([response], {type: 'application/pdf'});
const fileURL = URL.createObjectURL(file);
window.open(fileURL);
});
}
editItem(incident) {
this.router.navigate(['incidents/', incident.id]);
// this.comService.sendIncidentData(incident);
}
deleteItem(incidentID) {
console.log('delete: : ' + JSON.stringify(incidentID));
}
}
incidents-data-source.ts
import {Incident} from '../../incidents/incident';
import {DataSource} from '@angular/cdk/table';
import {MatPaginator, MatSort} from '@angular/material';
import {Observable} from 'rxjs/Observable';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {IncidentsCommunicationService} from '../services/incidents-communication.service';
export class IncidentsDataSource extends DataSource<any> {
filteredData: Incident[] = [];
renderedData: Incident[] = [];
filterChange = new BehaviorSubject('');
get filter(): string {
return this.filterChange.value;
}
set filter(filter: string) {
this.filterChange.next(filter);
}
get size(): number {
return this.comService.incidents.length;
}
constructor(private comService: IncidentsCommunicationService, private paginator: MatPaginator, private sort: MatSort) {
super();
this.filterChange.subscribe(() => this.paginator.pageIndex = 0);
}
/** Connect function called by the table to retrieve one stream containing the data to render. */
connect(): Observable<Incident[]> {
const displayDataChanges = [
this.comService.getIncidents(),
this.sort.sortChange,
this.filterChange,
this.paginator.page,
];
return Observable.merge(...displayDataChanges).map(() => {
this.renderedData = [];
if (this.comService.incidents.length > 0) {
// Filter data
this.filteredData = this.comService.incidents.slice().filter((item: Incident) => {
const searchStr = (
(item.protocolNo ? item.protocolNo : '') +
(item.date ? item.date : '') +
(item.patient ? item.patient.lastName : '') +
(item.doctor ? item.doctor.lastName : '') +
(item.clinic ? item.clinic.name : '') +
(item.isPayed ? 'Ναί' : 'Όχι') +
(item.signingDoctor ? item.signingDoctor.lastName : '')
).toLowerCase();
return searchStr.indexOf(this.filter.toLowerCase()) != -1;
});
// Sort filtered data
const sortedData = this.sortData(this.filteredData.slice());
// Grab the page's slice of the filtered sorted data.
const startIndex = this.paginator.pageIndex * this.paginator.pageSize;
this.renderedData = sortedData.splice(startIndex, this.paginator.pageSize);
}
return this.renderedData;
});
}
disconnect() {
this.comService.clearIncidents();
}
/** Returns a sorted copy of the database data. */
sortData(data: Incident[]): Incident[] {
if (!this.sort.active || this.sort.direction === '') {
return data;
}
return data.sort((a, b) => {
let propertyA: number | string = '';
let propertyB: number | string = '';
switch (this.sort.active) {
case 'protocolNo?':
[propertyA, propertyB] = [a.protocolNo, b.protocolNo];
break;
case 'date?':
[propertyA, propertyB] = [a.date, b.date];
break;
case 'patient?':
[propertyA, propertyB] = [a.patient.lastName, b.patient.lastName];
break;
case 'doctor?':
[propertyA, propertyB] = [a.doctor.lastName, b.doctor.lastName];
break;
case 'clinic?':
[propertyA, propertyB] = [a.clinic.name, b.clinic.name];
break;
case 'signingDoctor?':
[propertyA, propertyB] = [a.signingDoctor.lastName, b.signingDoctor.lastName];
break;
case 'isPayed?':
[propertyA, propertyB] = [Number(a.isPayed), Number(b.isPayed)];
break;
}
const valueA = isNaN(+propertyA) ? propertyA : +propertyA;
const valueB = isNaN(+propertyB) ? propertyB : +propertyB;
return (valueA < valueB ? -1 : 1) * (this.sort.direction === 'asc' ? 1 : -1);
});
}
}
incidents-communication.service.ts
import {Injectable} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {Incident} from '../../incidents/incident';
import {Patient} from '../../patients/patient';
import {Doctor} from '../../doctors/doctor';
import {Clinic} from '../../clinics/clinic';
@Injectable()
export class IncidentsCommunicationService {
incidentsSubject = new BehaviorSubject<Incident[]>([]);
get incidents(): Incident[] {
return this.incidentsSubject.value;
}
sendIncidents(incidents: Incident[]) {
this.incidentsSubject.next(incidents);
}
clearIncidents() {
this.incidentsSubject.next([]);
}
getIncidents(): Observable<Incident[]> {
return this.incidentsSubject.asObservable();
}
}
incidents.service.ts
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {Observable} from 'rxjs/Observable';
import {Incident} from './incident';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import {SigningDoctor} from '../signing-doctors/signing-doctor';
import {Patient} from '../patients/patient';
import {Doctor} from '../doctors/doctor';
import {Clinic} from '../clinics/clinic';
import {catchError} from 'rxjs/operators';
import 'rxjs/add/observable/forkJoin';
import {ErrorHandler} from '../shared/lib/error-handler';
@Injectable()
export class IncidentsService {
constructor(private http: HttpClient) {
}
getRelatedData() {
return Observable.forkJoin([this.getPatients(), this.getDoctors(), this.getClinics(), this.getSigningDoctors()]);
}
submitUpdateForm(value: Incident): Observable<Incident> {
const incidentPutURL = 'incidents/update/' + value.id;
// const httpOptions = {
// headers: new HttpHeaders({
// 'Content-Type': 'application/json',
// // 'Authorization': 'my-auth-token'
// })
// };
return this.http.put<Incident>(incidentPutURL, value)
.pipe(catchError(ErrorHandler.handleError));
}
submitForm(value: Incident): Observable<Incident> {
const incidentPostURL = 'incidents/new';
// const httpOptions = {
// headers: new HttpHeaders({
// 'Content-Type': 'application/json',
// // 'Authorization': 'my-auth-token'
// })
// };
return this.http.post<Incident>(incidentPostURL, value)
.pipe(catchError(ErrorHandler.handleError));
}
getIncidentByID(id: number): Observable<Incident> {
const incidentUrl = '/incidents/details/' + id;
return this.http.get<Incident>(incidentUrl)
.pipe(catchError(ErrorHandler.handleError));
}
getPdfById(id: number): Observable<Uint8Array> {
const pdfUrl = '/incidents/pdf/' + id;
// let headers = new HttpHeaders();
// headers = headers.set('Accept', 'application/pdf');
return this.http.get(pdfUrl, {responseType: 'arraybuffer'})
.map(response => new Uint8Array(response))
// .first()
.pipe(catchError(ErrorHandler.handleError));
}
getIncidents(): Observable<Incident[]> {
console.log('getting incidents');
const incidentsUrl = '/incidents/all';
return this.http.get<Incident[]>(incidentsUrl)
.pipe(catchError(ErrorHandler.handleError));
}
getPatients(): Observable<Patient[]> {
console.log('getting patients');
const patientsUrl = '/patients/all';
return this.http.get<Patient[]>(patientsUrl)
.pipe(catchError(ErrorHandler.handleError));
}
getDoctors(): Observable<Doctor[]> {
console.log('getting doctors');
const doctorsUrl = '/doctors/all';
return this.http.get<Doctor[]>(doctorsUrl)
.pipe(catchError(ErrorHandler.handleError));
}
getClinics(): Observable<Clinic[]> {
console.log('getting clinics');
const clinicsUrl = '/clinics/all';
return this.http.get<Clinic[]>(clinicsUrl)
.pipe(catchError(ErrorHandler.handleError));
}
getSigningDoctors(): Observable<SigningDoctor[]> {
console.log('getting signing doctors');
const signingDoctorsUrl = '/signingDoctors/all';
return this.http.get<SigningDoctor[]>(signingDoctorsUrl)
.pipe(catchError(ErrorHandler.handleError));
}
}
incident.ts
import {Patient} from '../patients/patient';
import {Clinic} from '../clinics/clinic';
import {Doctor} from 'app/doctors/doctor';
import {SigningDoctor} from '../signing-doctors/signing-doctor';
export class Incident {
private _id: number;
private _protocolNo: number;
private _date: any;
private _isPayed: boolean;
private _yliko: string;
private _makro: string;
private _anoso: string;
private _mikro: string;
private _symperasma: string;
private _patient: Patient;
private _clinic: Clinic;
private _doctor: Doctor;
private _histo: string;
private _klinikesPlirofories: string;
private _simpliromatikiEkthesi: string;
private _signingDoctor: SigningDoctor;
get id(): number {
return this._id;
}
set id(value: number) {
this._id = value;
}
get protocolNo(): number {
return this._protocolNo;
}
set protocolNo(value: number) {
this._protocolNo = value;
}
get date(): any {
return this._date;
}
set date(value: any) {
this._date = value;
}
get isPayed(): boolean {
return this._isPayed;
}
set isPayed(value: boolean) {
this._isPayed = value;
}
get yliko(): string {
return this._yliko;
}
set yliko(value: string) {
this._yliko = value;
}
get makro(): string {
return this._makro;
}
set makro(value: string) {
this._makro = value;
}
get anoso(): string {
return this._anoso;
}
set anoso(value: string) {
this._anoso = value;
}
get mikro(): string {
return this._mikro;
}
set mikro(value: string) {
this._mikro = value;
}
get symperasma(): string {
return this._symperasma;
}
set symperasma(value: string) {
this._symperasma = value;
}
get patient(): Patient {
return this._patient;
}
set patient(value: Patient) {
this._patient = value;
}
get clinic(): Clinic {
return this._clinic;
}
set clinic(value: Clinic) {
this._clinic = value;
}
get doctor(): Doctor {
return this._doctor;
}
set doctor(value: Doctor) {
this._doctor = value;
}
get histo(): string {
return this._histo;
}
set histo(value: string) {
this._histo = value;
}
get klinikesPlirofories(): string {
return this._klinikesPlirofories;
}
set klinikesPlirofories(value: string) {
this._klinikesPlirofories = value;
}
get simpliromatikiEkthesi(): string {
return this._simpliromatikiEkthesi;
}
set simpliromatikiEkthesi(value: string) {
this._simpliromatikiEkthesi = value;
}
get signingDoctor(): SigningDoctor {
return this._signingDoctor;
}
set signingDoctor(value: SigningDoctor) {
this._signingDoctor = value;
}
}
Everything works (data gets updated every time correct, filtering and pagination work fine), except shorting. Whenever i press a column header data is not shorted but shuffled some how. Any ideas why shorting is not working?? It should be the simplest think but its not. What am i doing wrong??
Thanks in advance!