角度垫表插入后不刷新

问题描述 投票:0回答:2

当我插入一本新书时,我想刷新我的角度材料表(mat-table)。 该表格不会自动刷新,我必须刷新浏览器才能看到插入的新书。

操作步骤

  1. 点击“创建”按钮”
  2. 填写 MatDialog 中的所有字段
  3. 单击“ENVOYER”按钮
  4. 数据库中插入了一本新书

但是表格不会自动加载最后插入的书。

我如何告诉我的 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/bibliofronthttps://jvmipwlay.github.stackblitz.io/books

有什么想法吗?

html angular typescript forms angular-material
2个回答
0
投票

这个问题与我在这个答案中用外行人的术语解释的问题非常相似。请先完成此操作,以便您知道在这里应该做什么不同的事情。

虽然您的

book.component
负责添加新书,而
booklist.component
负责显示所有书籍,但我们需要从
booklist
刷新
book
,但需要稍微扭转一下。

我观察到您通过

book.component
添加新书并触发
service.saveBook()
,然后通过
service.loadBooks()
触发
booklist.component
加载书籍数据。您已经拥有了双方共同的服务
book.service.ts
。好的。以下步骤都是基于这个假设,如果假设有误,请调整。

方式 1 - 更简单

步骤:

  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
          }
    
  2. book.service
    中,一旦触发
    sendUpdate
    ,它将在
    Subscription
    中提供值(比如说一个标志),并自动订阅调用
    Observers

  3. 观察者将在我们的

    booklist.component
    中,他们会订阅它。这意味着书单组件会自动知道添加了新书。

  4. 冰淇淋上的配料 - 现在订阅它时,您只需要触发您的

    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 -

  1. 当通过
    saveNewBook()
    成功添加一本书时,然后触发
    sendUpdate
    并发送结果,即新书的详细信息(而不是标志/消息)
  2. 现在,当结果被输入到订阅中时,我们可以通过订阅在书单组件中接收该书籍的详细信息。
  3. 在书单组件中,请勿调用
    chargerLivres()
    。相反,将特定的书籍详细信息添加到您现有的数据中(扭曲),您的数据将会刷新。

PS:我很感谢您在 stackblitz 中上传文件,但您的后端服务器位于您的本地主机 xD 上。因此,很难理解 api 架构。


0
投票

刷新 Angular 的 mat-table 数据源的最佳方法是重新分配相同的值。 因此,在提交时您可以做的是,这将确保刷新表。

this.dataSource = [...this.dataSource];

您还可以添加更改检测器,以便可以识别数据源值的任何更改并刷新表。

© www.soinside.com 2019 - 2024. All rights reserved.