0

I am using Vue 2 with Bootstrap Vue. I have a table for which I would like to be able to drag and drop these rows. But the way I implemented it does not work, but I don't know why. I am guessing the table structure messes things up, that's the only idea of mine. Here is the code:

I am using Vue 2 with Bootstrap Vue. I have a table for which I would like to be able to drag and drop these rows. But the way I implemented it does not work, but I don't know why. I am guessing the table structure messes things up, that's the only idea of mine. Here is the code:

<b-overlay
            :show="loading"
            rounded="sm"
            spinner-variant="primary"
        >
            <draggable
                v-model="accounts"
                @end="onDragEnd"
                tag="tbody"
                :move="onMove"
                :handle=".handle"
            >
                <b-table 
                    :fields="fields" 
                    :items="accounts" 
                    responsive 
                    head-variant="light"
                    tbody-tr-class="item"
                >
                    <template #head(handle)="data">
                        {{ '' }}
                    </template>

                    <template #cell(handle)="data">
                        <div class="handle-container">
                            <i class="fa fa-align-justify fa-lg handle"></i>
                        </div>
                    </template>

                    <template #cell(icon)="data">
                        <b-card
                            class="my-2"
                            :style="{ 'background-color': data.item.color }"
                        >
                            <b-card-sub-title>
                                <span v-html="getIcon(data.value)"></span>
                            </b-card-sub-title>
                        </b-card>
                    </template>

                    <template #cell(name)="data">
                        <b>{{ data.value }}</b>
                    </template>

                    <template #cell(balance)="data">
                        <span><i class="fas fa-euro-sign"></i> {{ data.value.toFixed(2) }}</span>
                    </template>

                    <template #cell(actions)="data">
                        <span class="cursor-pointer" v-b-modal="`bank-account-${data.item.id}-edit-modal`">
                            <i class="fas fa-edit fa-lg"></i>
                        </span>

                        <modal
                            :id="`bank-account-${data.item.id}-edit-modal`"
                            :title="$t('actions.edit-bank-account')"
                            :ok-disabled="!canSubmit"
                            @ok-pressed="$refs.form.submit()"
                        >
                            <add-bank-account-form 
                                ref="form"
                                :can-submit="canSubmit"
                                :id="data.item.id"
                                @form-updated="updateFormValidity"
                                @item-added="payload => itemUpdated(payload, data.item.id)"
                            />
                        </modal>

                        <span class="cursor-pointer trash-icon" @click="deleteItem(data.item.id)">
                            <i class="fas fa-trash fa-lg"></i>
                        </span>
                    </template>
                </b-table>
            </draggable>
        </b-overlay>

    import { mapGetters } from 'vuex';
    import Request from '@/mixins/Request';
    import draggable from 'vuedraggable';

    export default {
        components: {
            draggable,
        },
        mixins: [
            Request,
        ],
        data() {
            return {
                loading: false,
                accounts: [],
                canSubmit: false,
                fields: [
                    { key: 'handle', label: this.$t('misc.handle') },
                    { key: 'icon', label: this.$t('misc.type') },
                    { key: 'name', label: this.$t('misc.name') },
                    { key: 'balance', label: this.$t('misc.balance') },
                    { key: 'lastUpdate', label: this.$t('misc.last-update') },
                    { key: 'actions', label: this.$t('misc.actions') },
                ],
            };
        },
        computed: {
            ...mapGetters({
                activeUser: 'getActiveUser'
            }),
        },
        watch: {
            activeUser(newVal) {
                if (newVal) {
                    this.getBankAccounts();
                }
            },
        },
        methods: {
            async getBankAccounts() {
                this.loading = true;

                const { response } = await this.request('GET', '/bank-accounts', { params: { userId: this.activeUser.id, page: 1, perPage: 999 } });
                
                this.loading = false;

                this.accounts = response.data.data.map(account => ({
                    id: account.id,
                    handle: '',
                    icon: account.accountType.icon,
                    name: account.name,
                    balance: account.amount,
                    lastUpdate: account.updated_at ?? '-',
                    color: account.color,
                    actions: '',
                }));
            },
            getIcon(icon) {
                return `<i class="${icon} text-white fa-3x"></i>`;
            },
            updateFormValidity() {
                if (this.$refs.form) {
                    this.canSubmit = Object.values(this.$refs.form.item).every((value) => value);
                } else {
                    this.canSubmit = false;
                }
            },
            itemUpdated(data, bankAccountId) {
                this.$bvModal.hide(`bank-account-${bankAccountId}-edit-modal`);

                this.$toast.success(this.$t('messages.bank-account-updated'));

                this.getBankAccounts();
            },
            async deleteItem(id) {
                await this.request('DELETE', `/bank-accounts/${id}`);

                this.$toast.success(this.$t('messages.bank-account-deleted'));

                this.getBankAccounts();
            },
            onDragEnd() {
                // Handle the drag end event if you want to perform any actions
                // after the dragging is complete, such as saving the new order.
                console.log('Drag ended:', this.accounts);
                // Optionally, save the new order to the backend here.
                this.saveNewOrder();
            },
            onMove(evt, originalEvent) {
                // Additional logic to determine if a move is allowed
                // return true if allowed, false otherwise.
                return evt.from === evt.to; // Allow only within the same table
            },
            saveNewOrder() {
                // Here you would implement the logic to save the new order to the server
                console.log('New order saved:', this.accounts);
                // For example, you might make an API call to update the order
                this.request('PUT', '/bank-accounts/order', { data: this.accounts });
            },
        },
    };
2
  • does not work - What's actually happened? Commented Jun 25 at 13:00
  • The rows are not draggable.
    – screw4445
    Commented Jun 25 at 14:54

1 Answer 1

0

you can try this package for drag & drop which name is vuedraggable. you just need to pass a array in the vuedraggable and all of functionality will be handle he. you can follow this stacture:

<draggable :list="data" item-key="dp-social">
</draggable>

this is simple use case of the vuedraggable. inside the vuedraggable you write your component code or logic.

Not the answer you're looking for? Browse other questions tagged or ask your own question.