Vue.draggable: Dragging multiple rows of a table

Created on 12 Jun 2017  路  9Comments  路  Source: SortableJS/Vue.Draggable

I have a following problem:
I have products which have subproducts. I want to be able to drag the parent products while keeping all children products in order and under the parent. Essentially I have a following structure:

<table>
<thead>...</thead>
<tbody>
    <tr>
        <td>Parent 1</td>
    </tr>
    <tr>
        <td>Child 1 of parent 1</td>
    </tr>
    <tr>
        <td>Child 2 of parent 1</td>
    </tr>
    <tr>
        <td>Parent 2</td>
    </tr>
    <tr>
        <td>Child 1 of parent 2</td>
    </tr>
</tbody>
</table>

I have tried the following:

<draggable v-model="products"
           :options="{handle: '.handle', draggable: '.draggable'}"
           element="tbody"
>
    <template v-for="product in products">
        <tr class="draggable">
            <td class="handle">
                <i class="fa fa-ellipsis-v"></i>
                <i class="fa fa-ellipsis-v"></i>
            </td>
            <td>{{ product.name }}</td>
        </tr>
        <tr v-for="subproduct in product.subproducts">
            <td></td>
            <td>{{ subproduct.name }}</td>
        </tr>
    </template>
</draggable>

and it drags only the parent product(and also adds an undefined entry to the array).
Without the draggable: '.draggable' option I cannot drag at all(I can grab the row and move it around, but when I drop it the order doesn't change).

Is what I'm trying to achieve even possible with the table?

I'd appreciate any assistance.

question

Most helpful comment

@KKSzymanowski
I've been working on something similar. The only solution I've found is to have a tbody element for each product (containing rows for the product and each subproduct). Then your draggable tag needs element="table". This way instead of dragging rows within a tbody, you're dragging tbodys within a table.

The big problem is including a thead row. It needs to go inside the draggable element (since that's the table) which means you need a corresponding entry in your product list. That would be fine (if a little hacky), except that you also want to make the thead undraggable, and doing that results in erratic shuffling - often including the thead being pushed down the table - upon the end of any drag. The same thing happens if you make any tbody undraggable. It's not clear to me why this is.

So if you don't need a thead row, dragging tbodys within a table works great. If you do need a thead, the best solution I've found is putting it in a separate table and just styling it to look like they're connected.

All 9 comments

@KKSzymanowski , you should alter the HTML structure. Subproducts should be children element of products so drag operation could be done

Yeah, I figured so, but I have no idea how to do that with an HTML table. Do you know if it's possible at all?

I don`t have any answer off the top of my head.
HTML table are pretty tricky structure in general for dnd.

@KKSzymanowski
I've been working on something similar. The only solution I've found is to have a tbody element for each product (containing rows for the product and each subproduct). Then your draggable tag needs element="table". This way instead of dragging rows within a tbody, you're dragging tbodys within a table.

The big problem is including a thead row. It needs to go inside the draggable element (since that's the table) which means you need a corresponding entry in your product list. That would be fine (if a little hacky), except that you also want to make the thead undraggable, and doing that results in erratic shuffling - often including the thead being pushed down the table - upon the end of any drag. The same thing happens if you make any tbody undraggable. It's not clear to me why this is.

So if you don't need a thead row, dragging tbodys within a table works great. If you do need a thead, the best solution I've found is putting it in a separate table and just styling it to look like they're connected.

@jrwnz Thanks for your insight. Unfortunately I need a table header.

putting it in a separate table and just styling it to look like they're connected.

How would you approach that? Would you set the header column widths to match body column widths with JavaScript or is there some CSS/HTML hack to achieve that?

Check #61 - that will give you the right options for using a table

@stevieg83 Thanks. Unfortunately, I don't think any of the solutions there solve the problem here, which is sorting multiple rows at the same time.

@KKSzymanowski I still haven't found a totally satisfactory solution. Right now I'm just using CSS (header and body cells are assigned a class with a set width). That's fine for me, because I want my table to have a fixed width. If I wanted it to be responsive then it seems it'd be a little trickier (or at least require more screwing around with CSS) since the header and body cells seem to resize differently.

@jrwnz ah - my bad, I didn't realise you were looking to sort parent AND children.

Sortable.js does not allow sorting various element at the same time.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

AlexandreBonneau picture AlexandreBonneau  路  3Comments

ghost picture ghost  路  3Comments

Kgwkgwkgw picture Kgwkgwkgw  路  3Comments

Laraveldeep picture Laraveldeep  路  3Comments

Nrqz picture Nrqz  路  3Comments