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