0

* Project

I am creating a page where I retrieve player data from a json server, and I put the received data in a standard table with paginator.

* Problem

The table data need to be available before the "ngAfterViewInit()" is called the first time, but due to server response delay its not reliable and most of the time its called before the response is received which results in an empty table.

* What I already tried

I tried populating the table in the "ngAfterViewChecked()" function which resulted in displaying the table right 90% of the time but still its not reliable at all, also it produced another problem which is that the paginator and sort of the table need to be called at the "ngAfterViewInit()" only and not in the "ngAfterViewChecked()" so this effectively disabled these options.

* Code

  players: Player[];
  ppp:Player[];
  copy:Player[];
  errMess: string;
  displayedColumns = ['id', 'national_id', 'name', 'club_id', 'gov', 'age_level_id', 'weight', 'gender'];
  dataSource: MatTableDataSource<Player>;

  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;
  
  constructor(private playrService: PlayerService,
    @Inject('BaseURL') public BaseURL
    ) { 
    this.playrService.getPlayers().subscribe(response  => (this.players = response.data.players), errmess => this.errMess = <any>errmess);
    }
  ngAfterViewInit() {
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }
  ngAfterViewChecked() {
    this.dataSource = new MatTableDataSource(this.players);
    this.copy = this.players;
  }

  applyFilter(event: Event) {
    const filterValue = (event.target as HTMLInputElement).value;
    this.dataSource.filter = filterValue.trim().toLowerCase();
    if (this.dataSource.paginator) {
      this.dataSource.paginator.firstPage();
    }
  }

P.s: This is a standard table with paginator from Angular material Component, found here

* what's Expected

I need to be able to delay the population of the table until the data is received from the server as well as being able to use the paginator and the sort. or ideally just being able to populate the table and use paginator after the website is loaded and the data is received without the need of any intervention from the user "by clicking or any thing".

* Used Libraries and versions#

  • Angular V:5.1
  • Flex-Layout "angular" V: 2.00 beta 12
  • Angular Material V: 5.01
yousif fayed
  • 331
  • 1
  • 4
  • 20

1 Answers1

1

No, this is not asynchronous data works. You cannot in any way convert the asynchronous data to be synchronous. Any statements that directly depend on async data must be inside the subscription callback.

constructor(private playrService: PlayerService, @Inject('BaseURL') public BaseURL) { }

ngOnInit() {
  this.playrService.getPlayers().subscribe(
    response  => {
      this.players = response.data.players;
      this.dataSource = new MatTableDataSource(this.players);
      this.copy = this.players;                     // <-- redundant?
      this.dataSource.paginator = this.paginator;
      this.dataSource.sort = this.sort;
    }, 
    errmess => this.errMess = <any>errmess
  );
}

applyFilter(event: Event) {
  const filterValue = (event.target as HTMLInputElement).value;
  this.dataSource.filter = filterValue.trim().toLowerCase();
  if (this.dataSource.paginator) {
    this.dataSource.paginator.firstPage();
  }
}

Please go this answer and it's question to understand what you're trying isn't possible.

ruth
  • 29,535
  • 4
  • 30
  • 57
  • I get What you are saying but you didn't understand me correctly, i just want to delay the population of the table until my data is fetched or just populate it after the data is fetched correctly in any way, and as it turned out angular material had a pretty good way of doing that in their documentation "just little bit hidden away which is dumb of me not to look closely" but overall its similar to your code. thank you anyway. – yousif fayed Mar 19 '21 at 02:14