Nested virtual lists: Can I use a virtual list to create a collapsible sublist?

I can successfully place a collapsible list within a collapsible list when using HTML to make the list.

I was hoping I could use virtual lists to create this behavior. I am creating one virtual list with a custom renderItem function, and based on if the item has “children”, it will write a <div class="list virtual-list media-list" id="some different id"></div> within the accordion-item-content div of the template. Once the first virtual list’s rendering is complete, and I get the on itemsAfterInsert event to fire, I now create the nested virtual list, referencing the new base element by “some different id”. This nested virtual list method successfully will create collapsible lists within collapsible lists, but it is rendering weird and I cannot figure out why:

I am only wondering if it is not intended to work this way. Before I post code, I wanted to ensure whether or not this was supported.

The rendering of virtual lists is very different. Basically you only have the visible rows in your DOM and everything above and below gets removed on the fly while you are scrolling. The actual data is stored in e lightweight array or object. It actually simulates the scrolling of a long long list and therefore it is possible to have many thousand entries in a list without any performance issues. But the rendering is pretty limited. You need a fixed height for your rows - otherwise you get a weird result. If you want some nesting rows, you can probably solve this by adding the nested rows (insert the items in your data array) below the parent row and refresh the list. Actually it is not really nested, but you can style the rows a bit different (but keep the same height!).

But hey - do you really need virtual lists here? The performance is also great for the standard lists up to several hundred entries. As I explained above, there is only the visible stuff in DOM. So it is also not possible to use your browser search to find something outside the visible area nor you can do DOM manipulation here.

Thanks for your response. Virtual lists will come in handy because I am using these lists to model hierarchical/categorical transaction data, and I will be needing to remove list items and insert them, and virtual lists already have these capabilities built into them (they even have a scroll to item method too!). In the absence of a virtual list, I could have Vue/React data binding and offload the rendering to Vue or React, but then I’m on my own for manipulating the data and being able to scroll to certain elements.

Also, moving the virtual list outside of the parent list (to below it) allows it to render correctly, suggesting that a virtual list can only be right in the page-content div and not nested within anything else. I anticipate that the writers of this app only ever anticipated a virtual list being used this way.
This just leaves me to wonder if there is some DOM class manipulation I could do to allow it to render correctly (even if I can guarantee a constant height). It seems like it would stand to reason that if I can put a regular list into the accordion-item-content div of a list item, then I should be able to put a virtual list in this same div.

OK, it turns out that my only problem here was that I misplaced my </a> tag in my template, and I mistakenly had the accordion-item-content div within the anchor tag. This was causing the wacky rendering. I found this because when I copied the straight DOM-generated HTML (from the HTML inspector) and pasted it right into my HTML source, I was getting a list that looked the exact same — this clued me that the rendering had nothing to do with the virtual list. Once I moved the anchor tag to only encapsulate the item-inner div, the rendering completely fixed:

This at least proves that you can have one level deep of nested virtual lists. I cannot get it to work for two levels deep, but this is because as you said @VIEWSION that virtual lists require a constant height. I may alternatively to this just attempt to use Framework7-Vue so I can defer dynamic list generation to Vue instead of to the virtual list, but I got to admit, I thing Framework7 Core’s syntax is much cleaner.

Virtual List can be only one-level deep. There is no much sense to have VL render VL with each item, it will just discard all its advantages as having multiple VLs under VLs will consume a lot of memory, so no any performance gain

You can render Virtual List in Vue-way with Core VDOM router component. Check this demo: https://github.com/framework7io/framework7/blob/master/kitchen-sink/core/pages/virtual-list-vdom.html

Thanks @nolimits4web. Now, I was able to successfully nest several Virtual Lists within one another, but now I realize that this completely defeats the purpose of a virtual list. Now I also realize the other issue is that using a virtual list to render a model follows a more dated MVC approach where I am using the code to render the model. This is in contrast to a better way like you are suggesting where I use Vue to just bind to the model, which follows a more modern (as of 2018) MVVM approach, where the model is the first-class concept and I do not have to directly invoke controller-update logic every time the model changes. I will only use the virtual list for large sets of lazy loaded data.

1 Like