Skip to content

Commit c62d15d

Browse files
committed
feat(virtual-list): support virtual items auto height
1 parent b6de181 commit c62d15d

File tree

2 files changed

+39
-8
lines changed

2 files changed

+39
-8
lines changed

src/core/components/virtual-list/virtual-list-class.js

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ class VirtualList extends Framework7Class {
123123
maxBufferHeight: 0,
124124
listHeight: undefined,
125125
dynamicHeight: typeof vl.params.height === 'function',
126+
autoHeight: vl.params.height === 'auto',
126127
});
127128

128129
// Install Modules
@@ -170,10 +171,12 @@ class VirtualList extends Framework7Class {
170171
return vl;
171172
}
172173

173-
setListSize() {
174+
setListSize(autoHeightRerender) {
174175
const vl = this;
175176
const items = vl.filteredItems || vl.items;
176-
vl.pageHeight = vl.$scrollableParentEl[0].offsetHeight;
177+
if (!autoHeightRerender) {
178+
vl.pageHeight = vl.$scrollableParentEl[0].offsetHeight;
179+
}
177180
if (vl.dynamicHeight) {
178181
vl.listHeight = 0;
179182
vl.heights = [];
@@ -182,6 +185,27 @@ class VirtualList extends Framework7Class {
182185
vl.listHeight += itemHeight;
183186
vl.heights.push(itemHeight);
184187
}
188+
} else if (vl.autoHeight) {
189+
vl.listHeight = 0;
190+
if (!vl.heights) vl.heights = [];
191+
if (!vl.heightsCalculated) vl.heightsCalculated = [];
192+
const renderedItems = {};
193+
vl.$itemsWrapEl.find(`[data-virtual-list-index]`).forEach((el) => {
194+
renderedItems[parseInt(el.getAttribute('data-virtual-list-index'), 10)] = el;
195+
});
196+
for (let i = 0; i < items.length; i += 1) {
197+
const renderedItem = renderedItems[i];
198+
if (renderedItem) {
199+
if (!vl.heightsCalculated.includes(i)) {
200+
vl.heights[i] = renderedItem.offsetHeight;
201+
vl.heightsCalculated.push(i);
202+
}
203+
}
204+
if (typeof vl.heights[i] === 'undefined') {
205+
vl.heights[i] = 40;
206+
}
207+
vl.listHeight += vl.heights[i];
208+
}
185209
} else {
186210
vl.listHeight = Math.ceil(items.length / vl.params.cols) * vl.params.height;
187211
vl.rowsPerScreen = Math.ceil(vl.pageHeight / vl.params.height);
@@ -222,7 +246,7 @@ class VirtualList extends Framework7Class {
222246
let toIndex;
223247
let heightBeforeFirstItem = 0;
224248
let heightBeforeLastItem = 0;
225-
if (vl.dynamicHeight) {
249+
if (vl.dynamicHeight || vl.autoHeight) {
226250
let itemTop = 0;
227251
let itemHeight;
228252
vl.maxBufferHeight = vl.pageHeight;
@@ -292,7 +316,7 @@ class VirtualList extends Framework7Class {
292316

293317
// Set item top position
294318
if (i === fromIndex) {
295-
if (vl.dynamicHeight) {
319+
if (vl.dynamicHeight || vl.autoHeight) {
296320
topPosition = heightBeforeFirstItem;
297321
} else {
298322
topPosition = (i * vl.params.height) / vl.params.cols;
@@ -311,7 +335,7 @@ class VirtualList extends Framework7Class {
311335

312336
// Update list height with not updatable scroll
313337
if (!vl.updatableScroll) {
314-
if (vl.dynamicHeight) {
338+
if (vl.dynamicHeight || vl.autoHeight) {
315339
vl.itemsWrapEl.style.height = `${heightBeforeLastItem}px`;
316340
} else {
317341
vl.itemsWrapEl.style.height = `${(i * vl.params.height) / vl.params.cols}px`;
@@ -351,6 +375,11 @@ class VirtualList extends Framework7Class {
351375
items: renderExternalItems,
352376
});
353377
}
378+
if (vl.autoHeight) {
379+
requestAnimationFrame(() => {
380+
vl.setListSize(true);
381+
});
382+
}
354383
}
355384

356385
// Filter
@@ -381,7 +410,7 @@ class VirtualList extends Framework7Class {
381410
const vl = this;
382411
if (index > vl.items.length) return false;
383412
let itemTop = 0;
384-
if (vl.dynamicHeight) {
413+
if (vl.dynamicHeight || vl.autoHeight) {
385414
for (let i = 0; i < index; i += 1) {
386415
itemTop += vl.heights[i];
387416
}
@@ -407,6 +436,7 @@ class VirtualList extends Framework7Class {
407436
handleResize() {
408437
const vl = this;
409438
if (vl.isVisible()) {
439+
vl.heightsCalculated = [];
410440
vl.setListSize();
411441
vl.render(true);
412442
}
@@ -589,6 +619,7 @@ class VirtualList extends Framework7Class {
589619
if (deleteCache && vl.params.cache) {
590620
vl.domCache = {};
591621
}
622+
vl.heightsCalculated = [];
592623
vl.setListSize();
593624
vl.render(true);
594625
}

src/core/components/virtual-list/virtual-list.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ export namespace VirtualList {
8080
rowsAfter?: number;
8181
/** Number of items per row. Doesn't compatible when using Virtual List with dynamic height (default 1) */
8282
cols?: number;
83-
/** If number - list item height in px. If function then function should return item height. By default equals to 44 for iOS theme, 48 for MD theme, and 38 for Aurora theme */
84-
height?: number | Function;
83+
/** If number - list item height in px. If function then function should return item height. If "auto" - will automatically calculate each items heights. By default equals to 44 for iOS theme, 48 for MD theme, and 38 for Aurora theme */
84+
height?: number | Function | string;
8585
/** This optional function allows to use custom function to render item HTML. It could be used instead of template parameter */
8686
renderItem?(item: any): string;
8787
/** This optional function allows to render DOM items using some custom method. Useful in case it is used (e.g.) with Vue/React plugin to pass DOM rendering and manipulation to Vue/React. renderParameters conaints object with the following properties: fromIndex, toIndex, listHeight, topPosition, items */

0 commit comments

Comments
 (0)