Skip to content

Commit

Permalink
fix(virtual-scroll): JSX can render headers and footers
Browse files Browse the repository at this point in the history
  • Loading branch information
manucorporat committed May 10, 2018
1 parent 50021cd commit 012127d
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 44 deletions.
4 changes: 2 additions & 2 deletions angular/src/directives/virtual-scroll/virtual-scroll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ export class VirtualScroll {
private el: ElementRef,
public cd: ChangeDetectorRef,
) {
this.el.nativeElement.itemRender = this.itemRender.bind(this);
this.el.nativeElement.nodeRender = this.nodeRender.bind(this);
}

private itemRender(el: HTMLElement|null, cell: any, index?: number) {
private nodeRender(el: HTMLElement|null, cell: any, index?: number) {
if (!el) {
const node = this.itmTmp.viewContainer.createEmbeddedView(
this.getComponent(cell.type),
Expand Down
15 changes: 8 additions & 7 deletions core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ import {
HeaderFn,
ItemHeightFn,
ItemRenderFn,
NodeHeightFn,
} from './components/virtual-scroll/virtual-scroll-utils';

declare global {
Expand Down Expand Up @@ -7213,16 +7212,17 @@ declare global {
*/
'headerFn': HeaderFn;
'itemHeight': ItemHeightFn;
'itemRender': ItemRenderFn;
/**
* The data that builds the templates within the virtual scroll. It's important to note that when this data has changed, then the entire virtual scroll is reset, which is an expensive operation and should be avoided if possible.
*/
'items': any[];
'markDirty': (offset: number, len?: number) => void;
'markDirtyTail': () => void;
'nodeHeight': NodeHeightFn;
'nodeRender': ItemRenderFn;
'positionForItem': (index: number) => number;
'renderer': (item: any) => JSX.Element;
'renderFooter': (item: any, index: number) => JSX.Element;
'renderHeader': (item: any, index: number) => JSX.Element;
'renderItem': (item: any, index: number) => JSX.Element;
}
}

Expand Down Expand Up @@ -7267,13 +7267,14 @@ declare global {
*/
'headerFn'?: HeaderFn;
'itemHeight'?: ItemHeightFn;
'itemRender'?: ItemRenderFn;
/**
* The data that builds the templates within the virtual scroll. It's important to note that when this data has changed, then the entire virtual scroll is reset, which is an expensive operation and should be avoided if possible.
*/
'items'?: any[];
'nodeHeight'?: NodeHeightFn;
'renderer'?: (item: any) => JSX.Element;
'nodeRender'?: ItemRenderFn;
'renderFooter'?: (item: any, index: number) => JSX.Element;
'renderHeader'?: (item: any, index: number) => JSX.Element;
'renderItem'?: (item: any, index: number) => JSX.Element;
}
}
}
Expand Down
38 changes: 24 additions & 14 deletions core/src/components/virtual-scroll/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,6 @@ and what data to give to the header template. The function must return



#### itemRender




#### items


Expand All @@ -275,12 +270,22 @@ entire virtual scroll is reset, which is an expensive operation and
should be avoided if possible.


#### nodeHeight
#### nodeRender




#### renderFooter




#### renderHeader




#### renderer
#### renderItem



Expand Down Expand Up @@ -364,11 +369,6 @@ and what data to give to the header template. The function must return



#### item-render




#### items


Expand All @@ -379,12 +379,22 @@ entire virtual scroll is reset, which is an expensive operation and
should be avoided if possible.


#### node-height
#### node-render




#### render-footer




#### render-header




#### renderer
#### render-item



Expand Down
2 changes: 1 addition & 1 deletion core/src/components/virtual-scroll/test/basic.html
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
return el;
}

virtual.itemRender = (el, cell) => {
virtual.nodeRender = (el, cell) => {
if (cell.type === 0) return renderItem(el, cell.value);
return renderHeader(el, cell.value);
};
Expand Down
2 changes: 1 addition & 1 deletion core/src/components/virtual-scroll/test/cards.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
return el;
}

virtual.itemRender = (el, cell) => {
virtual.nodeRender = (el, cell) => {
if (cell.type === 0) return renderItem(el, cell.value);
return renderHeader(el, cell.value);
};
Expand Down
7 changes: 3 additions & 4 deletions core/src/components/virtual-scroll/virtual-scroll-utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ export interface VirtualNode {
const MIN_READS = 2;


export type NodeHeightFn = (node: VirtualNode, index: number) => number;
export type HeaderFn = (item: any, index: number, items: any[]) => string | null;
export type ItemHeightFn = (item: any, index?: number) => number;
export type ItemRenderFn = (el: HTMLElement|null, cell: Cell, domIndex?: number) => HTMLElement;
Expand Down Expand Up @@ -104,7 +103,7 @@ export function updateVDom(dom: VirtualNode[], heightIndex: Uint32Array, cells:

export function doRender(
el: HTMLElement,
itemRender: ItemRenderFn,
nodeRender: ItemRenderFn,
dom: VirtualNode[],
updateCellHeight: Function
) {
Expand All @@ -119,9 +118,9 @@ export function doRender(
if (node.change === NodeChange.Cell) {
if (i < childrenNu) {
child = children[i] as HTMLElement;
itemRender(child, cell, i);
nodeRender(child, cell, i);
} else {
child = itemRender(null, cell, i);
child = nodeRender(null, cell, i);
child.classList.add('virtual-item');
el.appendChild(child);
}
Expand Down
43 changes: 28 additions & 15 deletions core/src/components/virtual-scroll/virtual-scroll.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Component, Element, EventListenerEnable, Listen, Method, Prop, Watch } from '@stencil/core';
import { QueueController } from '../../interface';
import { Cell, DomRenderFn, HeaderFn, ItemHeightFn,
ItemRenderFn, NodeHeightFn, Range,
ItemRenderFn, Range,
VirtualNode, calcCells, calcHeightIndex, doRender,
findCellIndex, getRange, getShouldUpdate, getViewport,
inplaceUpdate, positionForIndex, resizeBuffer, updateVDom } from './virtual-scroll-utils';
inplaceUpdate, positionForIndex, resizeBuffer, updateVDom, CellType } from './virtual-scroll-utils';


@Component({
Expand Down Expand Up @@ -98,11 +98,15 @@ export class VirtualScroll {
* should be avoided if possible.
*/
@Prop() items?: any[];

@Prop() renderer?: (item: any) => JSX.Element;
@Prop() nodeHeight?: NodeHeightFn;
@Prop() itemHeight?: ItemHeightFn;
@Prop() itemRender?: ItemRenderFn;

// JSX API
@Prop() renderItem?: (item: any, index: number) => JSX.Element;
@Prop() renderHeader?: (item: any, index: number) => JSX.Element;
@Prop() renderFooter?: (item: any, index: number) => JSX.Element;

// Low level API
@Prop() nodeRender?: ItemRenderFn;
@Prop() domRender?: DomRenderFn;

@Watch('itemHeight')
Expand Down Expand Up @@ -255,11 +259,11 @@ export class VirtualScroll {
);

// write DOM
if (this.itemRender) {
doRender(this.el, this.itemRender, this.virtualDom, this.updateCellHeight.bind(this));
if (this.nodeRender) {
doRender(this.el, this.nodeRender, this.virtualDom, this.updateCellHeight.bind(this));
} else if (this.domRender) {
this.domRender(this.virtualDom);
} else if (this.renderer) {
} else if (this.renderItem) {
this.el.forceUpdate();
}
if (this.heightChanged) {
Expand Down Expand Up @@ -370,24 +374,33 @@ export class VirtualScroll {
}
}

renderVirtualNode(node: VirtualNode) {
const cell = node.cell;
switch(cell.type) {
case CellType.Item: return this.renderItem!(cell.value, cell.index);
case CellType.Header: return this.renderHeader!(cell.value, cell.index);
case CellType.Footer: return this.renderFooter!(cell.value, cell.index);
}
}

render() {
const renderer = this.renderer;
if (renderer) {
return this.virtualDom.map((dom) => {
const item = renderer(dom.cell.value) as any;
const renderItem = this.renderItem;
if (renderItem) {
return this.virtualDom.map((node) => {
const item = this.renderVirtualNode(node) as any;
const classes = ['virtual-item'];
if (!item.vattrs) {
item.vattrs = {};
}
item.vattrs.class += ' virtual-item';
if (!dom.visible) {
if (!node.visible) {
classes.push('virtual-loading');
}
item.vattrs.class += ' ' + classes.join(' ');
if (!item.vattrs.style) {
item.vattrs.style = {};
}
item.vattrs.style['transform'] = `translate3d(0,${dom.top}px,0)`;
item.vattrs.style['transform'] = `translate3d(0,${node.top}px,0)`;
return item;
});
}
Expand Down

0 comments on commit 012127d

Please sign in to comment.