Closed mesqueeb closed 5 years ago
Hello,
I thought you would use a new QExpansionItem, it handles visuals very well: https://v1.quasar-framework.org/vue-components/expansion-item#Example--Playing-with-inset-levels The arrow could be on the right and on the left which is desirable.
I think there are two main questions.
You are supporting the simple content and QItems and there are incompatibilities. a. In the first case, as I understand, it is up to developer to draw anything he wants. b. In the QItem (QExpansionItem exactly) the developer is presented with slots - coming from QExpansionItem/QItem interface, where he just can fill the defaults and quickly get the results. It is OK.
There is a fundamental conflict of impedancy in internal data structures and DOM presentation. You are using essentially a list processing but DOM is hierarchical and user/developer data are hierarchical, too. You are using internal list of nodes indexed by position and attributed by "depth" when both DOM and developer are using structures where either child node keeps parentID to his parent or parent node keeps childIDs list to all his children.
As for 1a I assume the interface should be similar to QTable in totally custom mode: https://v1.quasar-framework.org/vue-components/table#Example--Expanded-row-and-custom-selector They're using "body" slot, with "props" and developer can do what he just needs: <template v-slot:body="props">
As for 1b I think, that because it is your component, and your opinion and your needs, you are totally entitlet do make those visual and behavioral elements, as much compatible with QItem/QExpansion item as you wants. If anybody would want to make it more compatible, then there are pull requests and maybe even somebody will make another mode with another compound QElement.
As for 2 you are basically making internals of QTree, but with keyboard and mouse BUT and with much more UX friendliness. As for now, I compare your component more to the QTree than QList BUT - please consider the use case, when someone would want to use your component with QTable making it paged/sorted/filtered hierarchical table.
In essence: the use case 1b is the most important one, because its implementation would answer the rest of our questions. The data structure (list) is IMHO controversial because it limits relations between parent and childs. Those relations will eventually be expressed by events similar to "AllowDrop", "CanDrop", etc.
The keyboard navigation is just excellent BTW. I just can't wait when there will be possible to exchange/copy/move items between lists. Your component opens a whole new UX paradigm in Quasar!
Thank you for your advice. I'm going to let it sink and make an update tomorrow.
I already got my hands dirty today and I think I have found the perfect solution!!
BTW, the reason I want to work with a flat data structure and separate "depth", is because I highly prefer it over a nested data structure. In my use case it's much more performant than a nested structure that recursively builds the items.
I will explain why:
<template>
<rows>
<row v-for="rowData in rows" :rowData="rowData" />
</rows>
</template>
<!-- and each row would look like: -->
<row>
{{ rowData.body }}
<row
v-if="rowData.children"
style="margin-left: 2rem"
v-for="rowData in rows"
:rowData="rowData"
/>
</row>
This model is what I had for several years in my list app. But the problem is when each row can have a certain TAG and you filter by tags. If you filter on a tag and a bunch of rows have the tag you filter on but the parent rows don't have it, then Vue needs to re-create the components on the main level. This is veeery performance heavy if you want your items to be filtered fast.
<template>
<rows>
<row
v-for="rowData in rows"
:rowData="rowData"
/>
</rows>
</template>
With the current model as you know I just calculate the margin-left based on the depth that is passed. I have much more benefits with this model:
However, some things do get more complicated as well. I have no idea how I'm supposed to implement lazy-loading for instance, since it's not a nested structure XD.
I also can't use a QExpansionItem because I have a flat structure. However, of course I will try to make it look nice even without it.
Hmm, maybe you're on the right path and just leave the QItem compatibility and render this whole nodes and nodes groups as you see fit? This would be obviously much, much more performant. I'm thinking about thousands of nodes, and QItem really could lag here. If you render the nodes yourself, than you can paginate them, border them, and do anything. And in this case maybe this "depth" is everything you need. Hmm, you may be totally right and compatibility with QItem is wrong and "raw" rendering is right. QTree also renders itself as it sees fit. OK, I'm convinced, you have totally separate component and do not need to integrate with QList. If developer wants to put his own QListItem as a presentation of data, then it could be possible but only in the place you offered him. This place should be properly indented, and separated from the arrow. Yes, the performance argument beats the rest and gives a clear solutions for implementation. Thanks, when there is a talk there are ways, obviously.
@qyloxe I have finished Collapse/Expand š
check the demo: https://quasar-app-extension-draggable.netlify.com/
Nevertheless, i'll need to improve performance, because it's really bad with 200+ rows currently. :'(
PS: still TODO [BUG] Arrow down on collapsed row selects hidden child (#9)
@qyloxe I tackled some performance bottlenecks and currently the initial render is only 1.22 ms
per row, so about half a second for the 300 rows in the demo.
However, with using requestAnimationFrame
I was able to GREATLY improve collapse/expand performance. Check out 300 rows and try collapsing/expanding 299 of them. It's almost instant!
I will keep working to improve performance until I can render 9000 rows (#8) in an instant.
pushed performance a bit further, and fixed navigation bug š latest version now on npm
@qyloxe
I have finished implementing row expansion.
It's really useful with left/right arrow keys, but I'm not so satisfied with the dropdown-arrow. See this GIF:
The problem
You can see that if I put it inside a slot in my own component, it will not be a part of the row anymore, and then the dev will have to implement other ways to put the row CSS onto the new wrapper. This is very unhandy when using QItem! Because its CSS will not cover the actual arrow on the right...
Current implementation
Original structure:
The selection indicator is absolute and goes underneath the row content.
Now to add an arrow I changed it to:
And the new div has
flex
and doesflex 1
to the first child. I also passed a default arrow to the "collapse-arrow" slot.Main problem
When using things like QItem you'd want to place your "collapse-arrow" inside your QItem component you pass directly to my
<q-draggable-row>
. Like so:This is not possible with my current implementation.
My options
I could create a new
<q-draggable-row-collapse-arrow />
component instead. but how do I best link it to the "draggable-rows" ? the group component needs to know the state ofcollapsed
per row.Do you have any other advice for me?