Is there a way to move or rearrange columns in an HTML table using drag-and

I have a unique situation with my html table where I need to implement drag and drop functionality for columns instead of rows. My project is built using vue.js.

While it's straightforward to drag/drop rows by setting draggable="true" on the parent element, columns pose a challenge because each column is contained within its row parent. This means I can't simply apply draggable="true" to the entire column.

After researching, I came across the library at https://github.com/kutlugsahin/vue-smooth-dnd, but unfortunately, it does not provide an option for dragging columns.

I'm seeking advice on how to achieve this functionality. If possible, I would prefer a solution using the aforementioned plugin.

Answer №1

My implementation involves using a table component from Element UI and creating a custom method for enabling drag-and-drop functionality:

initializeDragAndDropFunctionality() {
  const tableColumn = this.$refs.tableRef.$el.querySelector(
    '.el-table__header-wrapper .el-table__header thead tr'
  );
  Sortable.create(tableColumn, {
    draggable: 'th',
    onEnd: this.dragReorderColumn
  });
}

This method is called when the Component mounts:

  mounted() {
    this.initializeTable();
  },

In order to make it work, you must assign a value to the "ref" attribute in the table:

  <el-table
      ref="tableRef"
    >
      <el-table-column
        v-for="(column, index) in tableTitles"
        :label="column.title"
        :prop="column.field"
        :width="column.width"
      >
      </el-table-column>
    </el-table>

The component also imports a utility class that leverages Sortablejs library:

import Sortable from 'sortablejs';

const vueSortable = {
  ...Sortable,
  create(el, options) {
    function swap(draggableSelector, movedElement, oldIndex, newIndex) {
      const parent = movedElement.parentNode;
      const cells = parent.querySelectorAll(draggableSelector);

      if (oldIndex > newIndex) {
        parent.insertBefore(movedElement, cells[newIndex]);
      } else {
        parent.insertBefore(movedElement, cells[newIndex].nextSibling);
      }
    }

    const tmpStorage = {};

    const newOptions = {
      ...options,
      onEnd(evt) {
        swap(options.draggable, evt.item, evt.newIndex, evt.oldIndex);

        tmpStorage.onChange = undefined;

        if (options.onEnd) {
          try {
            options.onEnd(evt);
          } catch (ex) {
            console.error('Error at onEnd:', ex);
          }
        }
      }
    };

    return Sortable.create(el, newOptions);
  }
};

export default vueSortable;

Answer №2

Have you ever tried dragging a column in a table? I stumbled upon this neat solution that makes it possible with just a simple adjustment to the thead key, resulting in the data being re-rendered.

<el-table border :data="tableData" size="mini" >
      <el-table-column
        v-for="(item, index) in elTheadList"
        :prop="dataTheadList[index]"
        :label='item'
        :key="`thead_${index}`"
       >
      </el-table-column>
    </el-table>
data() {
    return {
      tableData: [{
        date: '2016-05-01',
        name: 'Cristian Millan',
        address: 'Baja #11'
      },{
        date: '2016-05-02',
        name: 'Jorge Cabrera',
        address: 'Progreso #18'
      },{
        date: '2016-05-03',
        name: 'Armando Mendivil',
        address: 'Novena #12'
      }],
      dataTheadList: [
        'date',
        'name',
        'address'
      ],
      elTheadList: ['Date', 'Name', 'Address'],
    }
  },

mounted() {
   const el = document.querySelector('.el-table__header-wrapper tr')
   this.sortable = Sortable.create(el, {
    animation: 180,
    delay: 0,
    onEnd: evt => {
      const oldItem = this.dataTheadList[evt.oldIndex]
      this.dataTheadList.splice(evt.oldIndex, 1)
      this.dataTheadList.splice(evt.newIndex, 0, oldItem)
    }
  })
  }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilizing the output of a callback function to execute res.render in a NodeJS application

Currently, I am utilizing oracledb for node in order to retrieve data from the database. Once the data is fetched, my goal is to transmit it to the client side using render() in express JS. Below is an example of the code structure: config.js module.expo ...

Trigger a method within a component when there is a change in the Vuex state

I need to trigger a method inside a component whenever the vuex state changes in TypeScript and Vue.js. While I can access the vuex state value using getters in the template, I am unsure how to access the data within the component class. The vuex state is ...

Encountering an issue with the combination of SockJS and AngularJS: Error message

Currently experimenting with Angularjs and sockjs, utilizing this helpful resource: https://github.com/bendrucker/angular-sockjs On page load, I aim to transmit data via sockjs, however, encountering an Error: INVALID_STATE_ERR on the client side when att ...

Extension for Chrome browser

I am new to creating Chrome extensions and I am attempting to build one that will display the IDs of all elements with a specific class name on a website in the popup window. I would like to know if there is a better way to tackle this issue. Thank you for ...

Strange Phenomenon in Node/Express.js: Vanishing Array Elements

My goal is to extract information from a database and store it in an array for further processing. However, I am facing an issue where the elements disappear after being added in a for-loop, resulting in an empty array. // PROBLEM: all_prices-elements dis ...

Header frame is not valid

I have been working on developing a real-time application using NodeJS as my server and Socket.IO to enable live updates. However, I encountered an error message that reads: WebSocket connection to 'wss://localhost:1234/socket.io/?EIO=3&transpo ...

What is the significance of the "#" character in the URL of a jQuery mobile

As I encounter a strange issue with my jQuery mobile page, I notice that when accessing page.php everything looks good, but once adding #someDetailsHere to the URL, it only displays a blank white page. What could be causing this and how can I resolve it? ...

Having trouble establishing a connection with SignalR on my backend, it just doesn't seem to work properly

I am currently working on a project where I am using Vue with TypeScript and @microsoft/signalr. My goal is to create a chat feature using SignalR, and on the backend, I am utilizing C# with ASP.NET Core and docker. Here is the code snippet I have impleme ...

Issue with FontAwesome icon selection in Vue2 (nuxt) not displaying icons

If you're looking for the icon picker, you can find it here: https://github.com/laistomazz/font-awesome-picker I've tried running it, but unfortunately, the icons are not showing up. When I inspect the elements, the code is there but the icon is ...

Retrieve the element referred to as $el within a computed property

When attempting to retrieve this.$el.offsetTop within a computed property, the following error occurs: Cannot read property 'offsetTop' of undefined Is there a way to access the component's offsetTop in a computed method? If not, what is t ...

Merging two regular expressions for AngularJS form fields

How can I combine these two regex patterns for an AngularJS form field? \d{4}([- ]*)\d{6,7} OR [a-zA-Z0-9]{4,12} I attempted to do this like so: <input type="text" pattern="\d{4}([- ]*)\d{6,7} | [a-zA-Z0-9]{4,12}" class="form- ...

When using the Vuetify data table in single-select mode, choosing one row automatically selects all the other rows

I am having trouble selecting a single row from the table and then emitting the selected item. Currently, when I select one row, all rows become selected but only the first one encountered is saved to the model (as the selected variable). Could you provi ...

Create an array in JavaScript using the JSON data that was returned

After receiving some JSON data from a REST call, I have successfully parsed and added totals to the data. The results can be viewed on the page (refer to this post: json sibling data). However, now I want to further break down the totals. Here is the initi ...

Sending an AJAX request will only transmit a portion of an array when using the JSON.stringify

I have a JavaScript array that is constantly updated. Here's how I initially set up the array... columnArray = ["userID", "Date", "trialType", "cue", "target", "response", "accuracy", "lenAcc", "strictAcc", "fkpl", "totalTime"]; var dataArray = []; ...

Breaking down a string into an array using Node.js

Is there a way to change the following text into an array using nodejs? "Content: [{id: 1, value: 1, number: 1},{id: 13, value: 1, number: 3},{id: 14, value: 1, number: 3},]" I attempted to use JSON.parse, but encountered this error: Unexpected token c i ...

Encountered a cyclic dependency in MongoDB when attempting to create an index

I have a dataset structured as shown in the image below: https://i.sstatic.net/eu2ZH.png I am attempting to write a query using $near. However, when trying to create an index for this query, I encounter an error stating "cyclic dependency detected". Below ...

The array becomes empty after a value has been assigned to it

I am currently working with a variable containing JSON data. var blogData = [ { "blogTitle":"Bangladesh", "imagePath":"/img/blog/bangladesh.jpg" },{ "blogTitle":"In ...

Error encountered in Angular2 code due to a problem with inline templates

I'm grappling with the code below: import { Component } from '@angular/core'; @Component({ selector: 'character', template: `<h2 class="{{name}}">{{name}}</h2> <ul> ...

Enhancing data exchange with Axios and Sequelize

Encountering issues with an AXIOS GET request to my node sequelize backend. axios.get("/api/employees", { "params": { "where": { "id": 2 }, "include": { "name": "offices" } } }).then((response ...

Tips for using jest toHaveBeenCalled with multiple instances

Currently, I am in the process of writing a test case for one of my functions. This function calls another function from a library, and I am attempting to mock this function (saveCall). Below is a snippet of the sample code in question: import { Call } fro ...