如何在可滚动容器内跳转/滚动到材料表中的一行?

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

如果表格完全显示在页面中,只有页面滚动条,我就可以工作了。使用

scrollIntoView

但如果我的桌子位于具有固定高度和自己的滚动条的容器内,它就不再起作用了。

我拥有的功能:

onBeamIdInputChange(id: string) {
  const el = document.getElementById(id);
  if (el) {
    el.scrollIntoView({behavior: 'smooth', block: 'center'});
  }
}

在模板中使用此内容:

<td mat-cell *matCellDef="let i = index"> <span [id]="i"></span>{{ i }} </td>

但我需要保持标题 div 和表头始终可见。所以我尝试了容器的固定高度,但是跳转到特定行不再起作用,它只会以我的容器为中心。

我的html或多或少是这样的:

<div>Content to keep always visible - <input matInput type="text" ...>Jump to id</input></div>
<div id="container" style="height: 500px; overflow: auto;">
  <table mat-table> <!-- With sticky header -->
    ...
    <td mat-cell *matCellDef="let i = index"> <span [id]="i"></span>{{ i }} </td>
    ...
  </table>
</div>

如何跳转到具有这种嵌套滚动视图的单元格?

我尝试了https://stackoverflow.com/a/20958953/6165833将元素的父级的scrollTop设置为元素自己的offsetTop。但父级是

<ng-container matColumnDef="id">
而不是带有滚动区域的视图容器,所以它不起作用,而且对于角度组件来说似乎也有点脏。

编辑:在某些时候,我让它部分工作,自动滚动嵌套视图(容器),但前提是我之前滚动过主页。所以它会工作一次,然后就不再工作了,如果我在主页上再次滚动,它会再次工作一次等等。

就像如果我的页面已经以我的容器为中心,则对

scrollIntoView
的调用不起作用,但如果它必须以我的容器为中心,那么它也会在容器内滚动以显示搜索到的元素。

这种情况不再发生了,我不知道为什么不......

angular angular-material angular-material-table
2个回答
0
投票

最后我在容器上使用了

scrollTo
,并且需要计算偏移量。

@ViewChild('container') container: ElementRef;

onBeamIdInputChange(id: string) {
  const el = document.getElementById(id); // span element
  if (el) {
    const rowElement = el.parentElement.parentElement;
    // We substract the sticky header for the offset
    const offset = rowElement.offsetTop - rowElement.offsetHeight;
    this.container.nativeElement.scrollTo({
      top: offset,
      left: 0,
      behavior: 'smooth'
    });
  }
}

它似乎不是最干净或最强大的解决方案,但我没有找到任何其他方法让它工作。


0
投票

根据建议,我得到了比之前的解决方案更干净的东西,使用 Angular 来检索元素,而不是依赖于

.parentElement
调用。

@ViewChild('tableDiv') tableDiv: ElementRef;
@ViewChildren('idElement') idElements: QueryList<ElementRef>;

onIdInputChange(id: string) {
  const foundElement = this.idElements.toArray().find(item =>
    item.nativeElement.id === id).nativeElement;
  if (foundElement) {
    // We ignore the header + two rows
    const offset = foundElement.offsetTop - (foundElement.offsetHeight * 3);
    this.tableDiv.nativeElement.scrollTo({ top: offset, left: 0, behavior: 'smooth' });
  }
}

<div #tableDiv>
  <table mat-table [dataSource]="myData">
    <ng-container matColumnDef="id">
      <th mat-header-cell *matHeaderCellDef> ID </th>
      <td mat-cell *matCellDef="let dataRow" #idElement [id]="dataRow.id"> 
        { dataRow.id }}
      </td>
    </ng-container>
    ...
© www.soinside.com 2019 - 2024. All rights reserved.