|
| 1 | +**Warning: this component is still experimental. It may have bugs and the API may change at any |
| 2 | +time** |
| 3 | + |
| 4 | +`<cdk-virtual-scroll-viewport>` displays large lists of elements performantly by only |
| 5 | +rendering the items that fit on-screen. Loading hundreds of elements can be slow in any browser; |
| 6 | +virtual scrolling enables a performant way to simulate all items being rendered by making the |
| 7 | +height of the container element the same as the height of total number of elements to be rendered, |
| 8 | +and then only rendering the items in view. Virtual scrolling is different from strategies like |
| 9 | +infinite scroll where it renders a set amount of elements and then when you hit the end renders the |
| 10 | +rest. |
| 11 | + |
| 12 | +<!-- TODO(mmalerba): Add embedded examples once this is available in @angular/cdk --> |
| 13 | +For some example usages, |
| 14 | +[see the demo app](https://github.com/angular/material2/tree/master/src/demo-app/virtual-scroll). |
| 15 | + |
| 16 | +### Creating items in the viewport |
| 17 | +`*cdkVirtualFor` replaces `*ngFor` inside of a `<cdk-virtual-scroll-viewport>`, supporting the exact |
| 18 | +same API as [`*ngFor`](https://angular.io/api/common/NgForOf). |
| 19 | +The simplest usage just specifies the list of items: |
| 20 | + |
| 21 | +```html |
| 22 | +<cdk-virtual-scroll-viewport itemSize="50"> |
| 23 | + <div *cdkVirtualFor="let item of items">{{item}}</div> |
| 24 | +</cdk-virtual-scroll-viewport> |
| 25 | +``` |
| 26 | + |
| 27 | +`*cdkVirtualFor` makes the following context variables available to the template: |
| 28 | + |
| 29 | +| Context variable | Description | |
| 30 | +|------------------|----------------------------------------------------| |
| 31 | +| `index` | The index of the item in the data source. | |
| 32 | +| `count` | The total number of items in the data source. | |
| 33 | +| `first` | Whether this is the first item in the data source. | |
| 34 | +| `last` | Whether this is the last item in the data source. | |
| 35 | +| `even` | Whether the `index` is even. | |
| 36 | +| `odd` | Whether the `index` is odd. | |
| 37 | + |
| 38 | +All of these apply to the index of the item in the data source, not the index in the rendered |
| 39 | +portion of the data. |
| 40 | + |
| 41 | +```html |
| 42 | +<cdk-virtual-scroll-viewport itemSize="50"> |
| 43 | + <div *cdkVirtualFor="let item of items; |
| 44 | + let index = index; |
| 45 | + let count = count"> |
| 46 | + {{item}} ({{index}} of {{count}}) |
| 47 | + </div> |
| 48 | +</cdk-virtual-scroll-viewport> |
| 49 | +``` |
| 50 | + |
| 51 | +A `trackBy` function can be specified and works the same as the `*ngFor` `trackBy`. The `index` |
| 52 | +passed to the tracking function will be the index in the data source, not the index in the rendered |
| 53 | +portion. |
| 54 | + |
| 55 | +#### View recycling |
| 56 | +To improve rendering performance, `*cdkVirtualFor` caches previously created views after |
| 57 | +they are no longer needed. When a new view would normally be created, a cached view |
| 58 | +is reused instead. The size of the view cache can be adjusted via the `templateCacheSize` |
| 59 | +property; setting this size to `0` disables caching. If your templates are expensive in terms of |
| 60 | +memory you may wish to reduce this number to avoid spending too much memory on the template cache. |
| 61 | + |
| 62 | +```html |
| 63 | +<cdk-virtual-scroll-viewport itemSize="50"> |
| 64 | + <div *cdkVirtualFor="let item of items; templateCacheSize: 0">{{item}}</div> |
| 65 | +</cdk-virtual-scroll-viewport> |
| 66 | +``` |
| 67 | + |
| 68 | +#### Specifying data |
| 69 | +`*cdkVirtualFor` accepts data from an `Array`, `Observable<Array>`, or `DataSource`. The |
| 70 | +`DataSource` for the virtual scroll is the same one used by the table and tree components. A |
| 71 | +`DataSource` is simply an abstract class that has two methods: `connect` and `disconnect`. The |
| 72 | +`connect` method will be called by the virtual scroll viewport to receive a stream that emits the |
| 73 | +data array that should be rendered. The viewport will call `disconnect` when the viewport is |
| 74 | +destroyed, which may be the right time to clean up any subscriptions that were registered during the |
| 75 | +connect process. |
| 76 | + |
| 77 | +### Scrolling over fixed size items |
| 78 | +When all items are the same fixed size, you can use the `FixedSizeVirtualScrollStrategy`. This can |
| 79 | +be easily added to your viewport using the `itemSize` directive. The fixed size viewport strategy is |
| 80 | +less flexible than the autosize strategy because it requires all items to be the same size, but the |
| 81 | +advantage of this constraint is that it allows for better performance, since items do not need to be |
| 82 | +measured as they are rendered. |
| 83 | + |
| 84 | +```html |
| 85 | +<cdk-virtual-scroll-viewport itemSize="50"> |
| 86 | + ... |
| 87 | +</cdk-virtual-scroll-viewport> |
| 88 | +``` |
| 89 | + |
| 90 | +The fixed size strategy also supports setting the buffer size, i.e. the number of items rendered |
| 91 | +beyond the edge of the viewport. This can be adjusted by setting the `bufferSize` input. If |
| 92 | +`bufferSize` is not specified it defaults to 5 items. |
| 93 | + |
| 94 | +```html |
| 95 | +<cdk-virtual-scroll-viewport itemSize="50" bufferSize="1"> |
| 96 | + ... |
| 97 | +</cdk-virtual-scroll-viewport> |
| 98 | +``` |
| 99 | + |
| 100 | +**Note: The fixed size strategy will likely be changed to allow specifying a separate |
| 101 | +`minBufferPx` and `addBufferPx` like the autosize strategy** |
| 102 | + |
| 103 | +### Scrolling over items with different sizes |
| 104 | +When the items have different or unknown sizes, you can use the `AutoSizeVirtualScrollStrategy`. |
| 105 | +This can be added to your viewport by using the `autosize` directive. |
| 106 | + |
| 107 | +```html |
| 108 | +<cdk-virtual-scroll-viewport autosize> |
| 109 | + ... |
| 110 | +</cdk-virtual-scroll-viewport> |
| 111 | +``` |
| 112 | + |
| 113 | +The `autosize` strategy is configured through two inputs: `minBufferPx` and `addBufferPx`. |
| 114 | + |
| 115 | +**`minBufferPx`** determines the minimum space outside virtual scrolling viewport that will be |
| 116 | +filled with content. Increasing this will increase the amount of content a user will see before more |
| 117 | +content must be rendered. However, too large a value will cause more content to be rendered than is |
| 118 | +necessary. |
| 119 | + |
| 120 | +**`addBufferPx`** determines the amount of content that will be added incrementally as the viewport |
| 121 | +is scrolled. This should be greater than the size of `minBufferPx` so that one "render" is needed at |
| 122 | +a time. |
| 123 | + |
| 124 | +```html |
| 125 | +<cdk-virtual-scroll-viewport autosize minBufferPx="50" addBufferPx="100"> |
| 126 | + ... |
| 127 | +</cdk-virtual-scroll-viewport> |
| 128 | +``` |
| 129 | + |
| 130 | +Because the auto size strategy needs to measure the size of the elements, its performance may not |
| 131 | +be as good as the fixed size strategy. |
| 132 | + |
| 133 | +### Viewport orientation |
| 134 | +The virtual-scroll viewport defaults to a vertical orientation, but can also be set to |
| 135 | +`orientation="horizontal"`. When changing the orientation, ensure that the item are laid |
| 136 | +out horizontally via CSS. To do this you may want to target CSS at |
| 137 | +`.cdk-virtual-scroll-content-wrapper` which is the wrapper element that contains the rendered |
| 138 | +content. |
| 139 | + |
| 140 | +```html |
| 141 | +<cdk-virtual-scroll-viewport itemSize="50" orientation="horizontal"> |
| 142 | + ... |
| 143 | +</cdk-virtual-scroll-viewport> |
| 144 | +``` |
0 commit comments