license import { EmbeddedViewRef , IterableChangeRecord , IterableChanges , ViewContainerRef , } from '@angular/core' ; import { _ViewRepeater , _ViewRepeaterItemChanged , _ViewRepeaterItemContext , _ViewRepeaterItemContextFactory , _ViewRepeaterItemInsertArgs , _ViewRepeaterItemValueResolver , _ViewRepeaterOperation , } from './view-repeater' ; /**
 * A repeater that caches views when they are removed from a
 *  ViewContainerRef . When new items are inserted into the container,
 * the repeater will reuse one of the cached views instead of creating a new
 * embedded view. Recycling cached views reduces the quantity of expensive DOM
 * inserts.
 *
 *  template T template R template C export class _RecycleViewRepeaterStrategy < T , R , C extends _ViewRepeaterItemContext < T > > implements _ViewRepeater < T , R , C > { /**
     * The size of the cache used to store unused views.
     * Setting the cache size to `0` will disable caching. Defaults to 20 views.
     */ viewCacheSize : number = 20 ; /**
     * View cache that stores embedded view instances that have been previously stamped out,
     * but don't are not currently rendered. The view repeater will reuse these views rather than
     * creating brand new ones.
     *
     * TODO(michaeljamesparsons) Investigate whether using a linked list would improve performance.
     */ private _viewCache : EmbeddedViewRef < C > [ ] = [ ] ; /** Apply changes to the DOM. */ applyChanges ( changes , viewContainerRef , itemContextFactory , itemValueResolver , itemViewChanged ? ) { changes . forEachOperation ( ( record , adjustedPreviousIndex , currentIndex ) => { let view ; let operation ; if ( record . previousIndex == null ) { const viewArgsFactory = ( ) => itemContextFactory ( record , adjustedPreviousIndex , currentIndex ) ; view = this . _insertView ( viewArgsFactory , currentIndex ! , viewContainerRef , itemValueResolver ( record ) ) ; operation = view ? _ViewRepeaterOperation . INSERTED : _ViewRepeaterOperation . REPLACED ; } else if ( currentIndex == null ) { this . _detachAndCacheView ( adjustedPreviousIndex ! , viewContainerRef ) ; operation = _ViewRepeaterOperation . REMOVED ; } else { view = this . _moveView ( adjustedPreviousIndex ! , currentIndex ! , viewContainerRef , itemValueResolver ( record ) ) ; operation = _ViewRepeaterOperation . MOVED ; } if ( itemViewChanged ) { itemViewChanged ( { context : view ?. context , operation , record , } ) ; } } ) ; } detach ( ) { for ( const view of this . _viewCache ) { view . destroy ( ) ; } this . _viewCache = [ ] ; } /**
     * Inserts a view for a new item, either from the cache or by creating a new
     * one. Returns `undefined` if the item was inserted into a cached view.
     */ private _insertView ( viewArgsFactory , currentIndex , viewContainerRef , value ) { const cachedView = this . _insertViewFromCache ( currentIndex ! , viewContainerRef ) ; if ( cachedView ) { cachedView . context . $implicit = value ; return undefined ; } const viewArgs = viewArgsFactory ( ) ; return viewContainerRef . createEmbeddedView ( viewArgs . templateRef , viewArgs . context , viewArgs . index ) ; } /** Detaches the view at the given index and inserts into the view cache. */ private _detachAndCacheView ( index , viewContainerRef ) { const detachedView = viewContainerRef . detach ( index ) as EmbeddedViewRef < C > ; this . _maybeCacheView ( detachedView , viewContainerRef ) ; } /** Moves view at the previous index to the current index. */ private _moveView ( adjustedPreviousIndex , currentIndex , viewContainerRef , value ) { const view = viewContainerRef . get ( adjustedPreviousIndex ! ) as EmbeddedViewRef < C > ; viewContainerRef . move ( view , currentIndex ) ; view . context . $implicit = value ; return view ; } /**
     * Cache the given detached view. If the cache is full, the view will be
     * destroyed.
     */ private _maybeCacheView ( view , viewContainerRef ) { if ( this . _viewCache . length < this . viewCacheSize ) { this . _viewCache . push ( view ) ; } else { const index = viewContainerRef . indexOf ( view ) ; if ( index === - 1 ) { view . destroy ( ) ; } else { viewContainerRef . remove ( index ) ; } } } /** Inserts a recycled view from the cache at the given index. */ private _insertViewFromCache ( index , viewContainerRef ) { const cachedView = this . _viewCache . pop ( ) ; if ( cachedView ) { viewContainerRef . insert ( cachedView , index ) ; } return cachedView || null ; } }