【问题标题】:Update mat-table data after making change to database更改数据库后更新 mat-table 数据
【发布时间】:2018-07-02 20:41:23
【问题描述】:

首先,我只想说我对 Angular、Material 和 http 还很陌生,所以如果你能具体一点或包含一个代码 sn-p 以及任何响应,我将不胜感激。

我正在从 db2 数据库中提取数据并能够将其显示在 mat-table 中。我可以使用 matform 和 httpclientmodule 编辑数据库;但是,当我进行更改时,我无法在不重新加载页面的情况下刷新表格数据。

我尝试了分页器技巧(将分页器值设置为当前值以触发表更新),但我认为它在使用 http 时不起作用。

有人对此有好的解决方案吗?这是我的一些代码:

import {Component, AfterViewInit, ViewChild, Injectable, OnInit, 
ChangeDetectorRef} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {MatPaginator, MatSort, MatTableDataSource, MatInputModule, 
MatFormField, MatInput, MatFormFieldModule} from '@angular/material';
import {Observable} from 'rxjs/Observable';
import {merge} from 'rxjs/observable/merge';
import {of as observableOf} from 'rxjs/observable/of';
import {catchError, map, tap} from 'rxjs/operators';
import {startWith} from 'rxjs/operators/startWith';
import {switchMap} from 'rxjs/operators/switchMap';
import {SelectionModel} from '@angular/cdk/collections';
import { FormGroup, FormControl } from '@angular/forms';

export class ContractorsDao {
  constructor(private http: HttpClient) {}

  // Sends request including which field to sort by and to sort asc or desc
  getContractorRecords(sort: string, order: string, page: number): 
Observable<Contractor[]> {
    const href = 'http://localhost:8080/pzapp-servlet';
    const requestUrl =
      `${href}/controllercontractors?message=getMstx&sort=${sort}&order=${order}`;
    return this.http.post<Contractor[]>(requestUrl, 'getMstx');
  }
}

@Component({
  selector: 'app-search-contractors',
  templateUrl: 'contractors.component.html',
  styleUrls: ['./contractors.component.css']
})
export class ContractorsComponent implements AfterViewInit, OnInit {

// Initialize items for contractor mat-table

  // Columns displayed on the table
  displayedColumns = [
    'contractor-name',
    'contractor-phone',
    'select-contractor'
  ];

  // Initialize mat-table data source
  dataSource = new MatTableDataSource<Contractor>();

  // Initialize local database
  contractorDatabase: ContractorsDao | null;

  // Initialize mat-table features
  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;
  selection = new SelectionModel<Contractor>(false);

  editContractorForm: FormGroup;

  // Specific record selected
  activeRecord: Contractor;


  contractorsUrl = 'http://localhost:8080/pzapp-servlet/controllercontractors';

  // Triggered when record is selected from table
  viewRecord(row) {
    // Stores selected row for display
    this.activeRecord = row;
    this.editContractorForm = new FormGroup({
      NAME: new FormControl(this.activeRecord.NAME),
      PHON: new FormControl(this.activeRecord.PHON)
    });
  }

  // Takes filter text and filters table
  applyFilter(filterValue: string) {
    filterValue = filterValue.trim(); // Remove whitespace
    filterValue = filterValue.toLowerCase(); 
  // MatTableDataSource defaults to lowercase matches
    this.dataSource.filter = filterValue;
  }

  ngOnInit() {
    this.editContractorForm = new FormGroup({
    NAME: new FormControl(null),
    PHON: new FormControl(null),
    });
  }
  constructor(private http: HttpClient) {}

  ngAfterViewInit() {

    this.contractorDatabase = new ContractorsDao(this.http);
    this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0);

    merge(this.sort.sortChange, this.paginator.page)
      .pipe(
      startWith({}),
      switchMap(() => {
        return this.contractorDatabase.getContractorRecords(
          this.sort.active, this.sort.direction, this.paginator.pageIndex);
      }),

    ).subscribe(data => this.dataSource.data = data);
    this.dataSource.paginator = this.paginator;

  }
  onSubmit(value: any) {
    this.http.put(this.contractorsUrl, this.editContractorForm.value).subscribe();

  //  this.dataSource.paginator = this.paginator;
  }
}

// Interface for PZCNTR listing
export interface Contractor {
  PCNAME: string;
  PCPHON: number;
}

【问题讨论】:

    标签: angular angular-material2


    【解决方案1】:

    如果我正确理解了您的要求,您想要的是在数据库中的数据发生更改后自动重新加载数据。在我看来,您有以下选择。

    1. 使用计时器定期调用数据获取方法。这将是最容易实现的。见http://beyondscheme.com/2016/angular2-discussion-portal

      private refreshData(): void {
          //fetch data here
      }
      
      private subscribeToData(): void {
          this.timerSubscription = Observable.timer(5000).first().subscribe(() => this.refreshData());
      }
      
    2. 使用服务器端事件向前端获取通知,然后获取数据更改。在此处查看示例。 https://stackoverflow.com/a/41540858/1849366

    3. 使用网络套接字。见https://g00glen00b.be/spring-angular-sockjs/

    您会在网上获得更多关于上述方法的示例。

    【讨论】:

    • @downvoter 如果您也能解释下投票的原因,那就太好了。
    【解决方案2】:

    只需创建ContractorsDao 的新实例,并在成功编辑后将其分配给contractorDatabase 变量:

     onSubmit(value: any) {
        this.http.put(this.contractorsUrl, this.editContractorForm.value).subscribe(response => {
          this.contractorDatabase = new ContractorsDao(this.http);
          // here probably the rest of the code from ngAfterViewInit (so you can probably wrap it into a method)
        });    
      }
    

    【讨论】:

    • ^ 这个。 mat-table 监听整个数据数组的更改..而不是对其单个元素的更改....要单独更新每个元素,您必须使用其他路由...可能是由于 mat-table 是创建以显示静态数据比其他任何东西都多...也就是说...在模板中的单元格定义中,您仍然可以将变量绑定到所述数组的元素以更新它们...比如说 例如
    • Mateusz 我实际上已经尝试过了,但由于某种原因它不起作用
    • Mateusz Witkowski 我做了一些测试,它确实有效,但有时我需要调用两次 onSubmit 方法。你知道为什么会这样吗?
    • @Richard 你确定正确的(更改的)数据总是传递给onSubmit 方法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-09
    • 2021-12-11
    • 2011-03-05
    • 1970-01-01
    • 2011-09-13
    • 2021-07-08
    相关资源
    最近更新 更多