I'm trying to populate a table with a mat dialog and to use pagination after 5 added rows. Adding the data from the dialog works, but I cannot make the paginator work. I tried a lot of tutorial, but they only use static data or data loaded from API.
This is my code:
order.component.html:
<mat-grid-list cols="2" rowHeight="45px">
<mat-grid-tile id="customer">
<h1>{{ customer.name }} ({{ customer.code }})</h1>
</mat-grid-tile>
<mat-grid-tile id="buttons">
<button mat-button color="basic" (click)="openHelpDialog()">Help</button>
<button mat-button color="warn">Annulla (ESC)</button>
<button mat-button color="primary">Salva (F10)</button>
</mat-grid-tile>
</mat-grid-list>
<mat-grid-list cols="2" rowHeight="67px" style="font-size: 14px">
<mat-grid-tile>
<mat-form-field appearance="standard">
<mat-label>Pagamento</mat-label>
<input matInput #payment placeholder="Inserisci metodo di pagamento" maxlength="220">
<mat-hint align="end">{{ headNote.value.length}}/220</mat-hint>
</mat-form-field>
</mat-grid-tile>
<mat-grid-tile>
<mat-form-field appearance="standard">
<mat-label>Nota di testata</mat-label>
<input matInput #headNote placeholder="Aggiungi nota di testata" maxlength="220">
<mat-hint align="end">{{ headNote.value.length}}/220</mat-hint>
</mat-form-field>
</mat-grid-tile>
</mat-grid-list>
<mat-grid-list cols="2" rowHeight="67px" style="font-size: 14px">
<mat-grid-tile>
<mat-form-field appearance="standard">
<mat-label>Cerca</mat-label>
<input #autoInput autofocus type="text"
placeholder="Cerca un prodotto"
aria-label="Cerca"
matInput
[formControl]="myControl"
[matAutocomplete]="auto">
<mat-autocomplete autoActiveFirstOption #auto="matAutocomplete" (optionSelected)="openDialog($event)">
<mat-option *ngFor="let option of filteredOptions | async" [value]="option">
{{option}}
</mat-option>
</mat-autocomplete>
<button matSuffix mat-icon-button aria-label="Clear" (click)="myControl.reset()">
<mat-icon>close</mat-icon>
</button>
</mat-form-field>
</mat-grid-tile>
<mat-grid-tile>
<mat-form-field appearance="standard">
<mat-label>Nota di riga</mat-label>
<input matInput #rowNote placeholder="Aggiungi nota di riga" (keydown.enter)="onSaveRowNote($event)" (keydown.escape)="onEscape($event)" maxlength="75">
<mat-hint align="end">{{ rowNote.value.length}}/75</mat-hint>
</mat-form-field>
</mat-grid-tile>
</mat-grid-list>
<table #table mat-table [dataSource]="dataSource.data">
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef>
#
</th>
<td mat-cell *matCellDef="let element"> {{element.id}} </td>
</ng-container>
<ng-container matColumnDef="productCode">
<th mat-header-cell *matHeaderCellDef>
Codice Prodotto
</th>
<td mat-cell *matCellDef="let element"> {{element.productCode}} </td>
</ng-container>
<ng-container matColumnDef="productName">
<th mat-header-cell *matHeaderCellDef>
Nome prodotto
</th>
<td mat-cell *matCellDef="let element"> {{element.productName}} </td>
</ng-container>
<ng-container matColumnDef="aliasDescription">
<th mat-header-cell *matHeaderCellDef>
Alias
</th>
<td mat-cell *matCellDef="let element"> {{element.aliasDescription}} </td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef>
Quantità
</th>
<td mat-cell *matCellDef="let element"> {{element.amount}} </td>
</ng-container>
<ng-container matColumnDef="initialPrice">
<th mat-header-cell *matHeaderCellDef>
Prezzo di listino
</th>
<td mat-cell *matCellDef="let element"> {{element.initialPrice}} </td>
</ng-container>
<ng-container matColumnDef="discount">
<th mat-header-cell *matHeaderCellDef>
Sconto
</th>
<td mat-cell *matCellDef="let element"> {{element.discount}} </td>
</ng-container>
<ng-container matColumnDef="unitPrice">
<th mat-header-cell *matHeaderCellDef>
Prezzo scontato
</th>
<td mat-cell *matCellDef="let element"> {{element.unitPrice}} </td>
</ng-container>
<ng-container matColumnDef="totalPrice">
<th mat-header-cell *matHeaderCellDef>
Prezzo totale
</th>
<td mat-cell *matCellDef="let element"> {{ getTotalRow(element) | currency:'EUR' }} </td>
</ng-container>
<ng-container matColumnDef="comment">
<th mat-header-cell *matHeaderCellDef>
Comment
</th>
<td mat-cell *matCellDef="let element"> {{element.comment}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator
*ngIf="dataSource.data.length > 0"
[length]="dataSource.data.length"
[pageSizeOptions]="[2, 10, 20]"
showFirstLastButtons
aria-label="Seleziona la pagina degli ordini"></mat-paginator>
<div class="row">
<div>
<h5>Quantità totale</h5>
{{ getTotalQuantity() }}
</div>
<div>
<h5>Importo totale</h5>
{{ getTotalCost() | currency:'EUR' }}
</div>
</div>
order.component.ts:
import { Component, Inject, ViewChild, ElementRef, AfterViewInit, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Observable } from 'rxjs';
import { map, startWith } from 'rxjs/operators';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MatTable } from '@angular/material/table';
import { MatTableDataSource } from '@angular/material/table';
import { MatPaginator } from '@angular/material/paginator';
import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
export interface Customer {
name: string;
code: string;
}
export interface OrderRow {
id: number;
type: string;
productCode: string;
productName: string;
amount: number;
initialPrice: number;
unitPrice: number;
discount: string;
aliasCode: string;
aliasDescription: string;
totalPrice: number;
comment: string;
}
const ELEMENT_DATA: OrderRow[] = [];
@Component({
selector: 'app-order',
templateUrl: './order.component.html',
styleUrls: ['./order.component.scss']
})
export class OrderComponent implements AfterViewInit, OnInit {
customer: Customer = { name: "01 PROVA CLIENTE", code: "029.19599" }
row = {} as OrderRow;
myControl = new FormControl('');
displayedColumns: string[] = ['id', 'productCode', 'productName', 'aliasDescription', 'amount', 'initialPrice', 'discount', 'unitPrice', 'totalPrice'];
options: string[] = ['One', 'Two', 'Three', 'productCode', 'productName', 'amount', 'initialPrice'];
filteredOptions: Observable<string[]>;
dataSource = new MatTableDataSource(ELEMENT_DATA);
@ViewChild('table', { static: true, read: MatTable }) table: any;
@ViewChild(MatPaginator, {read: true}) paginator: MatPaginator;
@ViewChild('autoInput', { static: false })
set autoInput(element: ElementRef<HTMLInputElement>) {
if(element) {
element.nativeElement.focus()
}
}
constructor(public dialog: MatDialog) { }
ngOnInit() {
this.filteredOptions = this.myControl.valueChanges.pipe(
startWith(''),
map(value => this._filter(value || '')),
);
}
ngAfterViewInit() {
this.dataSource.paginator = this.paginator;
}
private _filter(value: string): string[] {
if (value.length < 3) { return []}
const filterValue = value.toLowerCase();
return this.options.filter(option => option.toLowerCase().includes(filterValue));
}
openHelpDialog() {
this.dialog.open(HelpDialog);
}
openDialog(event: MatAutocompleteSelectedEvent): void {
const dialogRef = this.dialog.open(AddProductDialog, {
data: {
id: this.dataSource.data.length + 1,
type: "product",
productCode: 2,
productName: event.option.value,
amount: 2,
initialPrice: 2,
unitPrice: 2,
discount: "20+10",
aliasCode: this.row.aliasCode,
aliasDescription: this.row.aliasDescription,
},
});
dialogRef.afterClosed().subscribe(result => {
if (result != undefined && Object.values(result).some(value => value != undefined && value != "" && value != null)) {
const data = this.dataSource.data;
data.unshift(result);
this.dataSource.data = data;
this.table.renderRows();
this.myControl.reset();
this.dataSource.paginator = this.paginator;
}
});
}
onEscape(e: any): void {
e.target.value = '';
}
onSaveRowNote(e: any): void {
let noteRow = {} as OrderRow;
noteRow.id = this.dataSource.data.length + 1;
noteRow.type = 'comment';
noteRow.amount = 0;
noteRow.productCode = "";
noteRow.productName = "";
noteRow.aliasCode = "";
noteRow.aliasDescription = "";
noteRow.initialPrice = 0;
noteRow.discount = "0";
noteRow.unitPrice = 0;
noteRow.comment = e.target.value;
this.dataSource.data.unshift(noteRow);
this.table.renderRows();
this.onEscape(e);
}
getTotalCost() {
return this.dataSource.data.map(t => t.amount * t.unitPrice).reduce((acc, value) => acc + value, 0);
}
getTotalQuantity() {
return this.dataSource.data.map(t => t.amount * 1).reduce((acc, value) => acc + value, 0);
}
getTotalRow(element: any) {
return element.amount * element.unitPrice;
}
}
@Component({
selector: 'app-order-help-dialog',
templateUrl: 'help-dialog.component.html',
})
export class HelpDialog {
constructor(
public dialogRef: MatDialogRef<HelpDialog>
) {}
onNoClick(): void {
this.dialogRef.close();
}
}
@Component({
selector: 'app-order-add-product',
templateUrl: 'add-product-dialog.html',
host: {
'(document:keydown)': 'handleKeyboardEvent($event)'
}
})
export class AddProductDialog {
constructor(
public dialogRef: MatDialogRef<AddProductDialog>,
@Inject(MAT_DIALOG_DATA) public data: OrderRow,
) {}
onNoClick(): void {
this.dialogRef.close();
}
handleKeyboardEvent(event: KeyboardEvent): void {
if (event.key === "F10"){
event.preventDefault();
console.log(this.data)
this.dialogRef.close((result: any) => { result });
}
}
}
add-product-dialog.html
<h1 mat-dialog-title>Seleziona prodotto</h1>
<div mat-dialog-content>
<mat-form-field appearance="standard">
<mat-label>Codice prodotto</mat-label>
<input matInput [(ngModel)]="data.productCode">
</mat-form-field>
<mat-form-field appearance="standard">
<mat-label>Nome prodotto</mat-label>
<input matInput [(ngModel)]="data.productName">
</mat-form-field>
<mat-form-field appearance="standard">
<mat-label>Quantità</mat-label>
<input matInput [(ngModel)]="data.amount">
</mat-form-field>
<mat-form-field appearance="standard">
<mat-label>Prezzo iniziale</mat-label>
<input matInput [(ngModel)]="data.initialPrice">
</mat-form-field>
<mat-form-field appearance="standard">
<mat-label>Prezzo unitario</mat-label>
<input matInput [(ngModel)]="data.unitPrice">
</mat-form-field>
<mat-form-field appearance="standard">
<mat-label>Sconto</mat-label>
<input matInput [(ngModel)]="data.discount">
</mat-form-field>
<mat-form-field appearance="standard">
<mat-label>Codice EAN</mat-label>
<input matInput [(ngModel)]="data.aliasCode">
</mat-form-field>
<mat-form-field appearance="standard">
<mat-label>Descrizione Alias</mat-label>
<input matInput [(ngModel)]="data.aliasDescription">
</mat-form-field>
</div>
<div mat-dialog-actions>
<button mat-button (click)="onNoClick()">Annulla</button>
<button mat-button [mat-dialog-close]="data">Aggiungi</button>
</div>