mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
docs(virtual-scroll): add live examples (#13327)
This commit is contained in:
@@ -27,11 +27,7 @@ rest.
|
||||
same API as [`*ngFor`](https://angular.io/api/common/NgForOf). The simplest usage just specifies the
|
||||
list of items:
|
||||
|
||||
```html
|
||||
<cdk-virtual-scroll-viewport itemSize="50">
|
||||
<div *cdkVirtualFor="let item of items">{{item}}</div>
|
||||
</cdk-virtual-scroll-viewport>
|
||||
```
|
||||
<!-- example(cdk-virtual-scroll-overview) -->
|
||||
|
||||
`*cdkVirtualFor` makes the following context variables available to the template:
|
||||
|
||||
@@ -47,15 +43,7 @@ list of items:
|
||||
All of these apply to the index of the item in the data source, not the index in the rendered
|
||||
portion of the data.
|
||||
|
||||
```html
|
||||
<cdk-virtual-scroll-viewport itemSize="50">
|
||||
<div *cdkVirtualFor="let item of items;
|
||||
let index = index;
|
||||
let count = count">
|
||||
{{item}} ({{index}} of {{count}})
|
||||
</div>
|
||||
</cdk-virtual-scroll-viewport>
|
||||
```
|
||||
<!-- example(cdk-virtual-scroll-context) -->
|
||||
|
||||
A `trackBy` function can be specified and works the same as the `*ngFor` `trackBy`. The `index`
|
||||
passed to the tracking function will be the index in the data source, not the index in the rendered
|
||||
@@ -68,11 +56,7 @@ is reused instead. The size of the view cache can be adjusted via the `templateC
|
||||
property; setting this size to `0` disables caching. If your templates are expensive in terms of
|
||||
memory you may wish to reduce this number to avoid spending too much memory on the template cache.
|
||||
|
||||
```html
|
||||
<cdk-virtual-scroll-viewport itemSize="50">
|
||||
<div *cdkVirtualFor="let item of items; templateCacheSize: 0">{{item}}</div>
|
||||
</cdk-virtual-scroll-viewport>
|
||||
```
|
||||
<!-- example(cdk-virtual-scroll-template-cache) -->
|
||||
|
||||
##### Specifying data
|
||||
`*cdkVirtualFor` accepts data from an `Array`, `Observable<Array>`, or `DataSource`. The
|
||||
@@ -83,17 +67,13 @@ data array that should be rendered. The viewport will call `disconnect` when the
|
||||
destroyed, which may be the right time to clean up any subscriptions that were registered during the
|
||||
connect process.
|
||||
|
||||
<!-- example(cdk-virtual-scroll-data-source) -->
|
||||
|
||||
#### Scrolling over fixed size items
|
||||
When all items are the same fixed size, you can use the `FixedSizeVirtualScrollStrategy`. This can
|
||||
be easily added to your viewport using the `itemSize` directive. The advantage of this constraint is
|
||||
that it allows for better performance, since items do not need to be measured as they are rendered.
|
||||
|
||||
```html
|
||||
<cdk-virtual-scroll-viewport itemSize="50">
|
||||
...
|
||||
</cdk-virtual-scroll-viewport>
|
||||
```
|
||||
|
||||
The fixed size strategy also supports setting a couple of buffer parameters that determine how much
|
||||
extra content is rendered beyond what is visible in the viewport. The first of these parameters is
|
||||
`minBufferPx`. The `minBufferPx` is the minimum amount of content buffer (in pixels) that the
|
||||
@@ -108,11 +88,7 @@ remaining. Since this is below `minBufferPx` the viewport must render more buffe
|
||||
least enough buffer to get back to `maxBufferPx`. In this case, it renders 4 items (an additional
|
||||
`200px`) to bring the total buffer size to `290px`, back above `maxBufferPx`.
|
||||
|
||||
```html
|
||||
<cdk-virtual-scroll-viewport itemSize="50" minBufferPx="100" maxBufferPx="250">
|
||||
...
|
||||
</cdk-virtual-scroll-viewport>
|
||||
```
|
||||
<!-- example(cdk-virtual-scroll-fixed-buffer) -->
|
||||
|
||||
Other virtual scrolling strategies can be implemented by extending `VirtualScrollStrategy`. An
|
||||
autosize strategy that works on elements of differing sizes is currently being developed in
|
||||
@@ -125,11 +101,7 @@ out horizontally via CSS. To do this you may want to target CSS at
|
||||
`.cdk-virtual-scroll-content-wrapper` which is the wrapper element that contains the rendered
|
||||
content.
|
||||
|
||||
```html
|
||||
<cdk-virtual-scroll-viewport itemSize="50" orientation="horizontal">
|
||||
...
|
||||
</cdk-virtual-scroll-viewport>
|
||||
```
|
||||
<!-- example(cdk-virtual-scroll-horizontal) -->
|
||||
|
||||
### Elements with parent tag requirements
|
||||
Some HTML elements such as `<tr>` and `<li>` have limitations on the kinds of parent elements they
|
||||
@@ -138,13 +110,4 @@ their proper parent, and then wrap the whole thing in a `cdk-virtual-scroll-view
|
||||
that the parent does not introduce additional space (e.g. via `margin` or `padding`) as it will
|
||||
interfere with the scrolling.
|
||||
|
||||
```html
|
||||
<cdk-virtual-scroll-viewport itemSize="50">
|
||||
<table>
|
||||
<tr *cdkVirtualFor="let row of rows">
|
||||
<td>{{row.first}}</td>
|
||||
<td>{{row.second}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</cdk-virtual-scroll-viewport>
|
||||
```
|
||||
<!-- example(cdk-virtual-scroll-dl) -->
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
.example-viewport {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.example-item-detail {
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.example-alternate {
|
||||
background: rgba(127, 127, 127, 0.3);
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<cdk-virtual-scroll-viewport [itemSize]="18 * 7" class="example-viewport">
|
||||
<div *cdkVirtualFor="let item of items;
|
||||
let index = index;
|
||||
let count = count;
|
||||
let first = first;
|
||||
let last = last;
|
||||
let even = even;
|
||||
let odd = odd;" [class.example-alternate]="odd">
|
||||
<div class="example-item-detail">Item: {{item}}</div>
|
||||
<div class="example-item-detail">Index: {{index}}</div>
|
||||
<div class="example-item-detail">Count: {{count}}</div>
|
||||
<div class="example-item-detail">First: {{first ? 'Yes' : 'No'}}</div>
|
||||
<div class="example-item-detail">Last: {{last ? 'Yes' : 'No'}}</div>
|
||||
<div class="example-item-detail">Event: {{even ? 'Yes' : 'No'}}</div>
|
||||
<div class="example-item-detail">Odd: {{odd ? 'Yes' : 'No'}}</div>
|
||||
</div>
|
||||
</cdk-virtual-scroll-viewport>
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import {ChangeDetectionStrategy, Component} from '@angular/core';
|
||||
|
||||
/** @title Virtual scroll context variables */
|
||||
@Component({
|
||||
selector: 'cdk-virtual-scroll-context-example',
|
||||
styleUrls: ['cdk-virtual-scroll-context-example.css'],
|
||||
templateUrl: 'cdk-virtual-scroll-context-example.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class CdkVirtualScrollContextExample {
|
||||
items = Array.from({length: 100000}).map((_, i) => `Item #${i}`);
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
.example-viewport {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.example-item {
|
||||
height: 50px;
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
<cdk-virtual-scroll-viewport itemSize="50" class="example-viewport">
|
||||
<div *cdkVirtualFor="let item of ds" class="example-item">{{item || 'Loading...'}}</div>
|
||||
</cdk-virtual-scroll-viewport>
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
import {CollectionViewer, DataSource} from '@angular/cdk/collections';
|
||||
import {ChangeDetectionStrategy, Component} from '@angular/core';
|
||||
import {BehaviorSubject, Observable, Subscription} from 'rxjs';
|
||||
|
||||
/** @title Virtual scroll with a custom data source */
|
||||
@Component({
|
||||
selector: 'cdk-virtual-scroll-data-source-example',
|
||||
styleUrls: ['cdk-virtual-scroll-data-source-example.css'],
|
||||
templateUrl: 'cdk-virtual-scroll-data-source-example.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class CdkVirtualScrollDataSourceExample {
|
||||
ds = new MyDataSource();
|
||||
}
|
||||
|
||||
export class MyDataSource extends DataSource<string | undefined> {
|
||||
private length = 100000;
|
||||
private pageSize = 100;
|
||||
private cachedData = Array.from<string>({length: this.length});
|
||||
private fetchedPages = new Set<number>();
|
||||
private dataStream = new BehaviorSubject<(string | undefined)[]>(this.cachedData);
|
||||
private subscription = new Subscription();
|
||||
|
||||
connect(collectionViewer: CollectionViewer): Observable<(string | undefined)[]> {
|
||||
this.subscription.add(collectionViewer.viewChange.subscribe(range => {
|
||||
const startPage = this.getPageForIndex(range.start);
|
||||
const endPage = this.getPageForIndex(range.end - 1);
|
||||
for (let i = startPage; i <= endPage; i++) {
|
||||
this.fetchPage(i);
|
||||
}
|
||||
}));
|
||||
return this.dataStream;
|
||||
}
|
||||
|
||||
disconnect(): void {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
|
||||
private getPageForIndex(index: number): number {
|
||||
return Math.floor(index / this.pageSize);
|
||||
}
|
||||
|
||||
private fetchPage(page: number) {
|
||||
if (this.fetchedPages.has(page)) {
|
||||
return;
|
||||
}
|
||||
this.fetchedPages.add(page);
|
||||
|
||||
// Use `setTimeout` to simulate fetching data from server.
|
||||
setTimeout(() => {
|
||||
this.cachedData.splice(page * this.pageSize, this.pageSize,
|
||||
...Array.from({length: this.pageSize})
|
||||
.map((_, i) => `Item #${page * this.pageSize + i}`));
|
||||
this.dataStream.next(this.cachedData);
|
||||
}, Math.random() * 1000 + 200);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
.example-viewport {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.example-dt {
|
||||
height: 30px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.example-dd {
|
||||
height: 30px;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<cdk-virtual-scroll-viewport class="example-viewport" itemSize="60">
|
||||
<dl class="example-dl">
|
||||
<ng-container *cdkVirtualFor="let state of states">
|
||||
<dt class="example-dt">{{state.name}}</dt>
|
||||
<dd class="example-dd">{{state.capital}}</dd>
|
||||
</ng-container>
|
||||
</dl>
|
||||
</cdk-virtual-scroll-viewport>
|
||||
@@ -0,0 +1,63 @@
|
||||
import {ChangeDetectionStrategy, Component} from '@angular/core';
|
||||
|
||||
/** @title Virtual scrolling `<dl>` */
|
||||
@Component({
|
||||
selector: 'cdk-virtual-scroll-dl-example',
|
||||
styleUrls: ['cdk-virtual-scroll-dl-example.css'],
|
||||
templateUrl: 'cdk-virtual-scroll-dl-example.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class CdkVirtualScrollDlExample {
|
||||
states = [
|
||||
{name: 'Alabama', capital: 'Montgomery'},
|
||||
{name: 'Alaska', capital: 'Juneau'},
|
||||
{name: 'Arizona', capital: 'Phoenix'},
|
||||
{name: 'Arkansas', capital: 'Little Rock'},
|
||||
{name: 'California', capital: 'Sacramento'},
|
||||
{name: 'Colorado', capital: 'Denver'},
|
||||
{name: 'Connecticut', capital: 'Hartford'},
|
||||
{name: 'Delaware', capital: 'Dover'},
|
||||
{name: 'Florida', capital: 'Tallahassee'},
|
||||
{name: 'Georgia', capital: 'Atlanta'},
|
||||
{name: 'Hawaii', capital: 'Honolulu'},
|
||||
{name: 'Idaho', capital: 'Boise'},
|
||||
{name: 'Illinois', capital: 'Springfield'},
|
||||
{name: 'Indiana', capital: 'Indianapolis'},
|
||||
{name: 'Iowa', capital: 'Des Moines'},
|
||||
{name: 'Kansas', capital: 'Topeka'},
|
||||
{name: 'Kentucky', capital: 'Frankfort'},
|
||||
{name: 'Louisiana', capital: 'Baton Rouge'},
|
||||
{name: 'Maine', capital: 'Augusta'},
|
||||
{name: 'Maryland', capital: 'Annapolis'},
|
||||
{name: 'Massachusetts', capital: 'Boston'},
|
||||
{name: 'Michigan', capital: 'Lansing'},
|
||||
{name: 'Minnesota', capital: 'St. Paul'},
|
||||
{name: 'Mississippi', capital: 'Jackson'},
|
||||
{name: 'Missouri', capital: 'Jefferson City'},
|
||||
{name: 'Montana', capital: 'Helena'},
|
||||
{name: 'Nebraska', capital: 'Lincoln'},
|
||||
{name: 'Nevada', capital: 'Carson City'},
|
||||
{name: 'New Hampshire', capital: 'Concord'},
|
||||
{name: 'New Jersey', capital: 'Trenton'},
|
||||
{name: 'New Mexico', capital: 'Santa Fe'},
|
||||
{name: 'New York', capital: 'Albany'},
|
||||
{name: 'North Carolina', capital: 'Raleigh'},
|
||||
{name: 'North Dakota', capital: 'Bismarck'},
|
||||
{name: 'Ohio', capital: 'Columbus'},
|
||||
{name: 'Oklahoma', capital: 'Oklahoma City'},
|
||||
{name: 'Oregon', capital: 'Salem'},
|
||||
{name: 'Pennsylvania', capital: 'Harrisburg'},
|
||||
{name: 'Rhode Island', capital: 'Providence'},
|
||||
{name: 'South Carolina', capital: 'Columbia'},
|
||||
{name: 'South Dakota', capital: 'Pierre'},
|
||||
{name: 'Tennessee', capital: 'Nashville'},
|
||||
{name: 'Texas', capital: 'Austin'},
|
||||
{name: 'Utah', capital: 'Salt Lake City'},
|
||||
{name: 'Vermont', capital: 'Montpelier'},
|
||||
{name: 'Virginia', capital: 'Richmond'},
|
||||
{name: 'Washington', capital: 'Olympia'},
|
||||
{name: 'West Virginia', capital: 'Charleston'},
|
||||
{name: 'Wisconsin', capital: 'Madison'},
|
||||
{name: 'Wyoming', capital: 'Cheyenne'},
|
||||
];
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
.example-viewport {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.example-item {
|
||||
height: 50px;
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
<cdk-virtual-scroll-viewport itemSize="50" minBufferPx="200" maxBufferPx="400"
|
||||
class="example-viewport">
|
||||
<div *cdkVirtualFor="let item of items" class="example-item">{{item}}</div>
|
||||
</cdk-virtual-scroll-viewport>
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import {ChangeDetectionStrategy, Component} from '@angular/core';
|
||||
|
||||
/** @title Fixed size virtual scroll with custom buffer parameters */
|
||||
@Component({
|
||||
selector: 'cdk-virtual-scroll-fixed-buffer-example',
|
||||
styleUrls: ['cdk-virtual-scroll-fixed-buffer-example.css'],
|
||||
templateUrl: 'cdk-virtual-scroll-fixed-buffer-example.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class CdkVirtualScrollFixedBufferExample {
|
||||
items = Array.from({length: 100000}).map((_, i) => `Item #${i}`);
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
.cdk-virtual-scroll-data-source-example .example-viewport {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.cdk-virtual-scroll-data-source-example .example-viewport .cdk-virtual-scroll-content-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.cdk-virtual-scroll-data-source-example .example-item {
|
||||
width: 50px;
|
||||
height: 100%;
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<div class="cdk-virtual-scroll-data-source-example">
|
||||
<cdk-virtual-scroll-viewport orientation="horizontal" itemSize="50" class="example-viewport">
|
||||
<div *cdkVirtualFor="let item of items" class="example-item">{{item}}</div>
|
||||
</cdk-virtual-scroll-viewport>
|
||||
</div>
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import {ChangeDetectionStrategy, Component, ViewEncapsulation} from '@angular/core';
|
||||
|
||||
/** @title Horizontal virtual scroll */
|
||||
@Component({
|
||||
selector: 'cdk-virtual-scroll-horizontal-example',
|
||||
styleUrls: ['cdk-virtual-scroll-horizontal-example.css'],
|
||||
templateUrl: 'cdk-virtual-scroll-horizontal-example.html',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class CdkVirtualScrollHorizontalExample {
|
||||
items = Array.from({length: 100000}).map((_, i) => `Item #${i}`);
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
.example-viewport {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.example-item {
|
||||
height: 50px;
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
<cdk-virtual-scroll-viewport itemSize="50" class="example-viewport">
|
||||
<div *cdkVirtualFor="let item of items" class="example-item">{{item}}</div>
|
||||
</cdk-virtual-scroll-viewport>
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import {ChangeDetectionStrategy, Component} from '@angular/core';
|
||||
|
||||
/** @title Basic virtual scroll */
|
||||
@Component({
|
||||
selector: 'cdk-virtual-scroll-overview-example',
|
||||
styleUrls: ['cdk-virtual-scroll-overview-example.css'],
|
||||
templateUrl: 'cdk-virtual-scroll-overview-example.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class CdkVirtualScrollOverviewExample {
|
||||
items = Array.from({length: 100000}).map((_, i) => `Item #${i}`);
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
.example-viewport {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.example-item {
|
||||
height: 50px;
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
<cdk-virtual-scroll-viewport itemSize="50" class="example-viewport">
|
||||
<div *cdkVirtualFor="let item of items; templateCacheSize: 0" class="example-item">{{item}}</div>
|
||||
</cdk-virtual-scroll-viewport>
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import {ChangeDetectionStrategy, Component} from '@angular/core';
|
||||
|
||||
/** @title Virtual scroll with no template caching */
|
||||
@Component({
|
||||
selector: 'cdk-virtual-scroll-template-cache-example',
|
||||
styleUrls: ['cdk-virtual-scroll-template-cache-example.css'],
|
||||
templateUrl: 'cdk-virtual-scroll-template-cache-example.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class CdkVirtualScrollTemplateCacheExample {
|
||||
items = Array.from({length: 100000}).map((_, i) => `Item #${i}`);
|
||||
}
|
||||
Reference in New Issue
Block a user