当我插入一本新书时,我想刷新我的角度材料表(mat-table)。 该表格不会自动刷新,我必须刷新浏览器才能看到插入的新书。
操作步骤
但是表格不会自动加载最后插入的书。
我如何告诉我的 booklist组件(显示垫子表的角度组件)自动添加新书而不刷新页面。
import { Component, OnInit, ViewChild } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table';
import {MatDialog, MatDialogConfig, MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
import { Book } from '../models/book';
import { BookService } from '../services/book.service';
import { BookComponent } from '../book/book.component';
//import { BookComponent } from '../book/book.component';
@Component({
selector: 'app-booklist',
templateUrl: './booklist.component.html',
styleUrls: ['./booklist.component.css']
})
export class BooklistComponent implements OnInit {
public pbookList;
booksResult: Book[] ;
dataSource;
searchKey: string;
// private dialog: MatDialog;
displayedColumns: string[] = ['titre', 'auteur','isbn', 'date enregistrement', 'date publication', 'actions'];
// dataSource = new MatTableDataSource<Book>(this.booksResult);
listData: MatTableDataSource<Book>;
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
constructor(private bookService: BookService, public dialog: MatDialog) { }
ngOnInit(): void {
this.chargerLivres();
this.dataSource = new MatTableDataSource<Book>(this.booksResult);
}
applyFilter() {
this.listData.filter = this.searchKey.trim().toLowerCase();
}
chargerLivres(){
console.log("list des books avant affcihage");
this.bookService.loadBooks().subscribe(
(result: Book[]) => {
console.log("list des books : ",result);
this.booksResult = result;
this.listData = new MatTableDataSource(result);
this.pbookList=result;
console.log("bookResult : ",this.booksResult);
},
error => {
console.log("Erreur : ",error);
}
);
}
onCreate() {
this.bookService.initializeFormGroup();
const dialogConfig = new MatDialogConfig();
dialogConfig.disableClose = true;
dialogConfig.autoFocus = true;
dialogConfig.width = "60%";
//dialogConfig.width = "350px";
this.dialog.open(BookComponent,dialogConfig);
}
}
<div class="container">
<div fxFlex="60">
<div class="search-div mr-2">
<button mat-raised-button (click)="onCreate()">
<mat-icon>add</mat-icon>Create
</button>
<mat-form-field class="ml-2 search-form-field" floatLabel="never">
<input matInput [(ngModel)]="searchKey" placeholder="Search" autocomplete="off" (keyup)="applyFilter()">
<button mat-button matSuffix mat-icon-button aria-label="Clear"*ngIf="searchKey" (click)="onSearchClear()">
<mat-icon>close</mat-icon>
</button>
</mat-form-field>
</div>
<div class="mat-elevation-z8">
<table mat-table [dataSource]="listData">
<ng-container matColumnDef="titre">
<th mat-header-cell *matHeaderCellDef> Titre </th>
<td mat-cell *matCellDef="let element"> {{element.title}} </td>
</ng-container>
<ng-container matColumnDef="auteur">
<th mat-header-cell *matHeaderCellDef> Auteur </th>
<td mat-cell *matCellDef="let element"> {{element.author}} </td>
</ng-container>
<ng-container matColumnDef="isbn">
<th mat-header-cell *matHeaderCellDef> Isbn </th>
<td mat-cell *matCellDef="let element"> {{element.isbn}} </td>
</ng-container>
<ng-container matColumnDef="date enregistrement">
<th mat-header-cell *matHeaderCellDef> Date enregistrement </th>
<td mat-cell *matCellDef="let element"> {{element.registerDate | date:'dd/MM/yyyy'}} </td>
</ng-container>
<ng-container matColumnDef="date publication">
<th mat-header-cell *matHeaderCellDef> Date publication </th>
<td mat-cell *matCellDef="let element"> {{element.releaseDate | date:'dd/MM/yyyy'}} </td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>Actions</th>
<td mat-cell *matCellDef="let row">
<button mat-icon-button><mat-icon>launch</mat-icon></button>
<button mat-icon-button color="warn"><mat-icon>delete_outline</mat-icon></button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator [pageSizeOptions]="[5, 10, 20]"></mat-paginator>
</div>
</div>
</div>
import { Component, Inject, OnInit } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { NgxSpinnerService } from 'ngx-spinner';
import { Book } from '../models/book';
import { BookService } from '../services/book.service';
@Component({
selector: 'app-book',
templateUrl: './book.component.html',
styleUrls: ['./book.component.css']
})
export class BookComponent implements OnInit {
public book = new Book();
constructor(public service: BookService, private spinner: NgxSpinnerService,public dialogRef: MatDialogRef<BookComponent>,@Inject(MAT_DIALOG_DATA) public data: any) { }
ngOnInit(): void {
}
onNoClick(): void {
this.dialogRef.close();
}
onSubmit() {
if (this.service.form.valid) {
const formValue = this.service.form.value;
this.book.author = formValue['auteur'];
this.book.isbn = formValue['isbNum'];
this.book.category = formValue['categ'];
this.book.title = formValue['titre'];
this.book.totalExamplaries = formValue['totExemplaire'];
var localDate = new Date(formValue['publiDate']);
if(localDate.getTimezoneOffset() < 0){
localDate.setMinutes(localDate.getMinutes() - localDate.getTimezoneOffset() );
}else{
localDate.setMinutes(localDate.getMinutes() + localDate.getTimezoneOffset() );
}
this.book.releaseDate = localDate;
if (!this.service.form.get('$key').value){
//Insert the new book
this.saveNewBook(this.book);
}
else {
this.service.form.reset();
}
}
}
/**
* Save new book
* @param book
*/
saveNewBook(book: Book){
this.spinner.show();
this.service.saveBook(book).subscribe(
(result: Book) => {
console.log("Resultat du livre : ",result);
if(result.id){
this.spinner.hide();
console.log("Le livre a ajoute avec id : ",result.id);
}
},
error => {
this.spinner.hide();
console.log("erreur survenue lors de ajout : ",error);
}
);
}
onClear() {
this.service.form.reset();
this.service.initializeFormGroup();
}
onClose() {
this.service.form.reset();
this.service.initializeFormGroup();
this.dialogRef.close();
}
/**
* Save zone local date to the book releaseDate property :
* there is a recognized problem with datepicker @angular/material timezone conversion.
* @param book
*/
setLocalDateToDatePicker(book: Book){
var localDate = new Date(book.releaseDate);
if(localDate.getTimezoneOffset() < 0){
localDate.setMinutes(localDate.getMinutes() - localDate.getTimezoneOffset() );
}else{
localDate.setMinutes(localDate.getMinutes() + localDate.getTimezoneOffset() );
}
book.releaseDate = localDate;
}
}
<mat-toolbar>
<span>{{service.form.controls['$key'].value?"Modifier un livre":"Nouveau livre"}}</span>
<span class="fill-remaining-space"></span>
<button class="btn-dialog-close ml-auto" mat-stroked-button (click)="onClose()" tabIndex="-1"><mat-icon>clear</mat-icon></button>
</mat-toolbar>
<form [formGroup]="service.form" class="normal-form" (submit)="onSubmit()">
<mat-grid-list cols="2" rowHeight="300px">
<mat-grid-tile>
<div class="controles-container">
<input type="hidden" formControlName="$key">
<mat-form-field>
<input formControlName="titre" matInput placeholder="Titre*" >
<mat-error>Le titre est obligatoire.</mat-error>
</mat-form-field>
<mat-form-field>
<input formControlName="auteur" matInput placeholder="Auteur*" >
<mat-error>Le nom de l'auteur est obligatoire.</mat-error>
</mat-form-field>
<mat-form-field>
<input formControlName="isbNum" matInput placeholder="Isbn*" >
<mat-error>L'isbn est obligatoire.</mat-error>
</mat-form-field>
</div>
</mat-grid-tile>
<mat-grid-tile>
<div class="controles-container">
<input type="hidden" value="test" name="test">
<mat-form-field>
<input formControlName="totExemplaire" type="number" matInput placeholder="Total Exemplaires*" >
<mat-error>Le nombre d'exemplaire est obligatoire.</mat-error>
</mat-form-field>
<mat-form-field>
<input formControlName="publiDate" [matDatepicker]="myDatepicker" matInput placeholder="Date publication*" >
<mat-datepicker-toggle matSuffix [for] = "myDatepicker" placeholder="mm/dd/yyyy">
</mat-datepicker-toggle><mat-datepicker #myDatepicker></mat-datepicker>
<mat-error>Le date est obligatoire.</mat-error>
</mat-form-field>
<mat-form-field>
<mat-select formControlName="categ" placeholder="Categorie" >
<ng-container >
<mat-option value="C">Cuisine</mat-option>
<mat-option value="I">Informatique</mat-option>
<mat-option value="J">Jeunesse</mat-option>
<mat-option value="M">Mathématiques</mat-option>
<mat-option value="B">Bande dessiné</mat-option>
</ng-container>
</mat-select>
</mat-form-field>
<div class="button-row">
<button mat-raised-button color="primary" class="mr-2" type="submit" [disabled]="service.form.invalid">Envoyer</button>
<button mat-raised-button color="warn" (click)="onClear()">Effacer</button>
</div>
</div>
</mat-grid-tile>
</mat-grid-list>
</form>
这是 stackblitz 链接:https://stackblitz.com/github/lnquaidorsay/bibliofront 或 https://jvmipwlay.github.stackblitz.io/books
有什么想法吗?
这个问题与我在这个答案中用外行人的术语解释的问题非常相似。请先完成此操作,以便您知道在这里应该做什么不同的事情。
虽然您的
book.component
负责添加新书,而 booklist.component
负责显示所有书籍,但我们需要从 booklist
刷新 book
,但需要稍微扭转一下。
我观察到您通过
book.component
添加新书并触发 service.saveBook()
,然后通过 service.loadBooks()
触发 booklist.component
加载书籍数据。您已经拥有了双方共同的服务book.service.ts
。好的。以下步骤都是基于这个假设,如果假设有误,请调整。
方式 1 - 更简单
步骤:
当您从
service.saveBook()
触发 saveNewBook()
时,您需要调用 Service.sendUpdate
(就像我回答中的那样)并简单地在成功时发送一个标志(简单的方式)。
saveNewBook(book: Book){
this.service.saveBook(book).subscribe(
(result: Book) => {
console.log("Resultat du livre : ",result);
if(result.id){
this.service.sendUpdate('A msg/flag');
// rest code same
}
},
//rest code same
}
在
book.service
中,一旦触发sendUpdate
,它将在Subscription
中提供值(比如说一个标志),并自动订阅调用Observers
。
观察者将在我们的
booklist.component
中,他们会订阅它。这意味着书单组件会自动知道添加了新书。
冰淇淋上的配料 - 现在订阅它时,您只需要触发您的
chargerLivres()
- 它似乎负责获取。
export class BooklistComponent implements OnDestroy {
messageReceived: any;
private subscriptionName: Subscription; //important to create a subscription
constructor(pprivate bookService: BookService) {
// subscribe to sender component messages
this.subscriptionName= this.bookService.getUpdate().subscribe
(message => { //message contains the data sent from service
this.messageReceived = message; //kind of a flag here
chargerLivres(); //or ngOnInit() whichever responsible for laoding
});
虽然上述方法很简单,但在仅添加一本书时加载所有书籍数据可能会产生问题!希望我们也能解决这个问题,但需要一些额外的工作 xD
方式 2 -
saveNewBook()
成功添加一本书时,然后触发sendUpdate
并发送结果,即新书的详细信息(而不是标志/消息)chargerLivres()
。相反,将特定的书籍详细信息添加到您现有的数据中(扭曲),您的数据将会刷新。PS:我很感谢您在 stackblitz 中上传文件,但您的后端服务器位于您的本地主机 xD 上。因此,很难理解 api 架构。
刷新 Angular 的 mat-table 数据源的最佳方法是重新分配相同的值。 因此,在提交时您可以做的是,这将确保刷新表。
this.dataSource = [...this.dataSource];
您还可以添加更改检测器,以便可以识别数据源值的任何更改并刷新表。