Как поддерживать вертикальную прокрутку при обновлении Таблицы данных Angular 5?

Я хотел бы часто обновлять таблицу данных (Covalent td-data-table несколько ng-template) С новыми данными, извлеченными из API REST JSON. Больше строк, чем поместится в браузере, поэтому пользователю может потребоваться прокрутка по вертикали. Но когда я обновляю данные в таблице, он полностью перерисовывается, т. е. вертикальное положение прокрутки сбрасывается наверх, всплывают подсказки и т. д..

хаки, например, сохранить / восстановить вертикальную прокрутку, такую как ниже вид работы, но они создают много визуального беспорядка, особенно в Браузер firefox.

// save vertical scroll
this.scrollTop = this.tableElt.nativeElement.querySelector('.td-data-table-scrollable').scrollTop;

// update table data here
this.data = newData;

// restore vertical scroll
setImmediate(() => {
    this.tableElt.nativeElement.querySelector('.td-data-table-scrollable').scrollTop = this.scrollTop;
  }
});

как я могу чисто обновить данные в таблице (или любой компонент на самом деле) без взлома, чтобы сбросить позиции прокрутки и мириться с большим количеством мигающего поведения?

Если нет решения с использованием ковалентной таблицы данных, есть ли другой угловой элемент управления 2+, который обрабатывает это правильно?

анимированный захват экрана проблемы: вертикальная прокрутка возвращается при обновлении данных. Вертикальная прокрутка должна поддерживаться между данными новинки. screencapture

4 ответов


Я предлагаю вам переключиться на угловой материал и привязать его к обозримому источников данных.

https://material.angular.io/components/table/overview#observable-stream-of-data-arrays

когда источник данных (наблюдаемый) обновляется новыми данными, он обновит DOM, и не будет необходимости следить за событиями прокрутки.

Если вы беспокоитесь о количестве элементов, перечисленных на странице, поддерживает разбиение на страницы простым способом; . https://material.angular.io/components/table/overview#pagination

SideNote: переключитесь на угловой материал, поскольку их компоненты хорошо документированы, с примерами и образцами кодов Дай мне знать, если застрянешь.


вы можете попробовать использовать функцию trackBy. Эта функция будет использоваться для определения того, какие строки вашего *ngFor изменились для оптимизации перерисовок.

<tbody>
<tr td-data-table-row *ngFor="let row of basicData; trackBy: getRowId">
  <td td-data-table-cell *ngFor="let column of columns" [numeric]="column.numeric">
    {{column.format ? column.format(row[column.name]) : row[column.name]}}
  </td>
  <td td-data-table-cell (click)="openPrompt(row, 'comments')">
    <button mat-button [class.mat-accent]="!row['comments']">{{row['comments'] || 'Add Comment'}}</button>
  </td>
</tr>
</tbody>

и затем в вашем машинописном тексте:

getRowById(index, row) {
   // Return some unique primitive idenitifier (string, number, etc.)
   return row['some unique property'];
}

подробнее о trackBy проверьте:

https://netbasal.com/angular-2-improve-performance-with-trackby-cc147b5104e5 https://blog.angular-university.io/angular-2-ngfor/

также, фабриката необходмо предусмотреть-строительство объекта DataTable очень хорошо для этого случая использования. Он встроен в виртуальную прокрутку. https://github.com/swimlane/ngx-datatable


похоже, когда вы получаете больше данных, вы обновляете весь список(массив, используемый в *ngFor), поэтому angular снова рисует полную таблицу. Попробуйте поместить в этот массив только разностные данные.


нажатие данных на ту же переменную массива, которая используется *ngFor не будет повторно отображать html.

простой пример:https://angular-frjdnf.stackblitz.io

Edit:

Я сделал пример проекта с ковалентной таблицей, используя *ngFor с угловым обновлением только дополнительной строки и не перерисовывая всю таблицу.

ссылка на Стакблиц.образец io проект.

HTML-код

<button (click)="addData()">Add Data</button>
<table td-data-table>
    <thead>
    <tr td-data-table-column-row>
      <td td-data-table-column *ngFor="let column of columns">
        {{column.label}}
      </td>
    </tr>
    </thead>
    <tbody>
    <tr td-data-table-row *ngFor="let row of basicData">
      <td td-data-table-cell *ngFor="let column of columns">
        {{ row[column.name] }}
      </td>
    </tr>
    </tbody>
  </table>

TS

basicData имеет начальные данные, которые были загружены в таблицу, и я просто нажимаю некоторые фиктивные данные при нажатии кнопки "Добавить данные" на basicData для тестирования полосы прокрутки.

import { Component } from '@angular/core';
import { ITdDataTableColumn } from '@covalent/core/data-table';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  columns: ITdDataTableColumn[] = [
    { name: 'first_name',  label: 'First Name' },
    { name: 'last_name', label: 'Last Name' },
    { name: 'gender', label: 'Gender' }
  ];

  count = 0;

  basicData: any[] = [
    {
      "first_name": "Sully",
      "gender": "Male",
      "last_name": "Clutterham"
    },
    ...
  ]

  additionalData: any[] = [
    {
      "first_name": "Sully",
      "gender": "Male",
      "last_name": "Clutterham"
    },
    ...
  ]

  addData(){
    if(this.count >= this.additionalData.length)
      this.count = 0;

    this.basicData.push(this.additionalData[this.count]);
    this.count++;
  }

}

надеюсь, что это помогает.