@@ -67,7 +67,7 @@ import {
6767 Subject ,
6868 Subscription ,
6969} from 'rxjs' ;
70- import { auditTime , filter , map , takeUntil } from 'rxjs/operators' ;
70+ import { auditTime , takeUntil } from 'rxjs/operators' ;
7171import { CdkColumnDef } from './cell' ;
7272import {
7373 BaseRowDef ,
@@ -1490,26 +1490,15 @@ export class CdkTable<T>
14901490
14911491 viewport . attach ( {
14921492 dataStream : this . _dataStream ,
1493- measureRangeSize : ( ) => {
1494- // TODO(crisbeto): implement this method so autosizing works.
1495- if ( typeof ngDevMode === 'undefined' || ngDevMode ) {
1496- throw new Error ( 'autoSize is not supported for tables with virtual scroll enabled.' ) ;
1497- }
1498- return 0 ;
1499- } ,
1493+ measureRangeSize : ( range , orientation ) => this . _measureRangeSize ( range , orientation ) ,
15001494 } ) ;
15011495
1502- const offsetFromTopStream = this . viewChange . pipe (
1503- map ( ( ) => viewport . getOffsetToRenderedContentStart ( ) ) ,
1504- filter ( offset => offset !== null ) ,
1505- ) ;
1506-
15071496 // The `StyickyStyler` sticks elements by applying a `top` or `bottom` position offset to
15081497 // them. However, the virtual scroll viewport applies a `translateY` offset to a container
15091498 // div that encapsulates the table. The translation causes the rows to also be offset by the
15101499 // distance from the top of the scroll viewport in addition to their `top` offset. This logic
15111500 // negates the translation to move the rows to their correct positions.
1512- combineLatest ( [ offsetFromTopStream , this . _headerRowStickyUpdates ] )
1501+ combineLatest ( [ viewport . renderedContentOffset , this . _headerRowStickyUpdates ] )
15131502 . pipe ( takeUntil ( this . _onDestroy ) )
15141503 . subscribe ( ( [ offsetFromTop , update ] ) => {
15151504 if ( ! update . sizes || ! update . offsets || ! update . elements ) {
@@ -1531,7 +1520,7 @@ export class CdkTable<T>
15311520 }
15321521 } ) ;
15331522
1534- combineLatest ( [ offsetFromTopStream , this . _footerRowStickyUpdates ] )
1523+ combineLatest ( [ viewport . renderedContentOffset , this . _footerRowStickyUpdates ] )
15351524 . pipe ( takeUntil ( this . _onDestroy ) )
15361525 . subscribe ( ( [ offsetFromTop , update ] ) => {
15371526 if ( ! update . sizes || ! update . offsets || ! update . elements ) {
@@ -1595,6 +1584,51 @@ export class CdkTable<T>
15951584
15961585 this . _changeDetectorRef . markForCheck ( ) ;
15971586 }
1587+
1588+ /**
1589+ * Measures the size of the rendered range in the table.
1590+ * This is used for virtual scrolling when auto-sizing is enabled.
1591+ */
1592+ private _measureRangeSize ( range : ListRange , orientation : 'horizontal' | 'vertical' ) : number {
1593+ if ( range . start >= range . end || orientation !== 'vertical' ) {
1594+ return 0 ;
1595+ }
1596+
1597+ const renderedRange = this . viewChange . value ;
1598+ const viewContainerRef = this . _rowOutlet . viewContainer ;
1599+
1600+ if (
1601+ ( range . start < renderedRange . start || range . end > renderedRange . end ) &&
1602+ ( typeof ngDevMode === 'undefined' || ngDevMode )
1603+ ) {
1604+ throw Error ( `Error: attempted to measure an item that isn't rendered.` ) ;
1605+ }
1606+
1607+ const renderedStartIndex = range . start - renderedRange . start ;
1608+ const rangeLen = range . end - range . start ;
1609+ let firstNode : HTMLElement | undefined ;
1610+ let lastNode : HTMLElement | undefined ;
1611+
1612+ for ( let i = 0 ; i < rangeLen ; i ++ ) {
1613+ const view = viewContainerRef . get ( i + renderedStartIndex ) as EmbeddedViewRef < unknown > | null ;
1614+ if ( view && view . rootNodes . length ) {
1615+ firstNode = lastNode = view . rootNodes [ 0 ] ;
1616+ break ;
1617+ }
1618+ }
1619+
1620+ for ( let i = rangeLen - 1 ; i > - 1 ; i -- ) {
1621+ const view = viewContainerRef . get ( i + renderedStartIndex ) as EmbeddedViewRef < unknown > | null ;
1622+ if ( view && view . rootNodes . length ) {
1623+ lastNode = view . rootNodes [ view . rootNodes . length - 1 ] ;
1624+ break ;
1625+ }
1626+ }
1627+
1628+ const startRect = firstNode ?. getBoundingClientRect ?.( ) ;
1629+ const endRect = lastNode ?. getBoundingClientRect ?.( ) ;
1630+ return startRect && endRect ? endRect . bottom - startRect . top : 0 ;
1631+ }
15981632}
15991633
16001634/** Utility function that gets a merged list of the entries in an array and values of a Set. */
0 commit comments