Vue 2.0's Sortable.js is not sorting items correctly

Currently, I am utilizing Sortable.js and Vue.js in my project. The main objective is to sort items while keeping the data updated.

Previously, everything was functioning smoothly with Vue 1.x. However, upon updating to version 2.0, the sorting started to display inaccuracies. Despite the array being updated correctly, the items in the DOM are now appearing in incorrect positions.

new Vue({
  el: '#app',
  template: '#sort',
  data: function() {
    return {
      items: [
        "http://placehold.it/200X300?text=image1",
        "http://placehold.it/200X300?text=image2",
        "http://placehold.it/200X300?text=image3",
        "http://placehold.it/200X300?text=image4"
      ],  
    }
  },
  mounted: function() {
    this.$nextTick(function () {
      Sortable.create(document.getElementById('sortable'), {
        animation: 200,
        onUpdate: this.reorder.bind(this),
      });
    })
  },
  methods: {
    reorder: function(event) {
        var oldIndex = event.oldIndex,
            newIndex = event.newIndex;
        this.items.splice(newIndex, 0, this.items.splice(oldIndex, 1)[0]);

    } 
   }
});

Here's the link to the code snippet on jsFiddle: https://jsfiddle.net/4bvtofdd/4/

I would greatly appreciate any assistance or insights on how to resolve this issue. Thank you!

Answer №1

Dealing with a similar issue today.

Make sure to include the :key attribute to ensure proper re-rendering of elements in Vue after Sortable changes the order of items.

<div v-for="item in items" :key="item.id">
  <!-- content -->
</div>

https://v2.vuejs.org/v2/guide/list.html#key

Answer №2

It just so happens that Sortable keeps track of the order in sortable.toArray(), making it simple to create a computed property that will display the items in sorted order without altering the original list.

new Vue({
  el: '#app',
  template: '#sort',
  data: {
    items: [
      "http://placehold.it/200X300?text=image1",
      "http://placehold.it/200X300?text=image2",
      "http://placehold.it/200X300?text=image3",
      "http://placehold.it/200X300?text=image4"
    ],
    order: null
  },
  computed: {
    sortedItems: function() {
      if (!this.order) {
        return this.items;
      }
      return this.order.map((i) => this.items[i]);
    }
  },
  mounted: function() {
    this.$nextTick(() => {
      const sortable = Sortable.create(document.getElementById('sortable'), {
        animation: 200,
        onUpdate: () => { this.order = sortable.toArray(); }
      });
    })
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/Sortable/1.4.2/Sortable.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="//unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4b372a382e74292d36213634311c30293b">[email protected]</a>/dist/vue.js"></script>
<div id='app'></div>
<template id="sort">
  <div class="container">
    <div class="row sort-wrap" id="sortable">
      <div class="col-xs-6 col-md-3 thumbnail" v-for="(item, index) in items" :data-id="index">
        <img v-bind:src="item" alt="" class="img-responsive">
      </div>
    </div>
    <div v-for="item in sortedItems">
    {{item}}
    </div>
  </div>
</template>

Answer №3

Double check that you're not relying on a prop for sorting, as it may cause issues. Instead, store the prop data in a data attribute and utilize that for sorting purposes.

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

Creating routes in Node.js after setting up middleware

Currently tackling a project using node.js and encountering a specific issue. After setting up all routes with express (app.get("..", func)), I find myself stuck with a middleware that catches all requests and redirects to a 404-page. The problem arises w ...

Swap out original source files in HTML with minified versions

I have successfully utilized a maven plugin to create a minified and compressed version of my CSS and JavaScript files. Now, I am looking to update the section in my main HTML page that currently loads all those individual files. Here is what it looks lik ...

Having trouble with the $.each function?

Values from the database row units for values salam & salavat are as follows: [these values were inserted using json_encode()] salam: [{"name_units":"salam","price_units":"74,554","checkbox_units":["minibar","mobleman"]},{"name_units":"mokhles","pr ...

The input value in the HTML form was altered momentarily before reverting back to its original state

Researching this topic was quite challenging, but keep reading to find out why. My objective is to detect any changes in a form field so that I can enable the "Save" button. While this seems easy enough, there's a catch. If the user reverts the input ...

Guide to integrating animations into a React JS array sorting program

I am currently working on a project that utilizes react js to visually sort an array. I have successfully implemented the sorting algorithm, and the website now displays the correctly sorted array. However, I would like to incorporate an animation to show ...

extracting ng-repeat values and passing them to the controller

I have created a form that dynamically increases whenever the user clicks on the add sale button Here is the HTML code: <fieldset data-ng-repeat="choice in choices"> <div class="form-group"> <label for="name"> Qu ...

Logs from console.log() statements in Firebase functions are missing

I've encountered an issue with the function below where the console.log() statements do not appear in the Firebase logs. When I remove everything after the db.collection call, the initial console.log() statements are visible. However, once I reintrodu ...

What is the best way to create space between table rows without using border-spacing?

I've been attempting to use the margin-bottom property on my table in order to separate the rows, but it doesn't seem to have any effect. I then tried using flex, which did work, but the table rows did not inherit the width and I had to specify a ...

Model Abstracted Aurelia Validation

I recently completed an online course on Aurelia by Scott Allen where he introduced the Aurelia-Validation plugin for form validation. As a result, my view-model now looks like this in edit.js: import {inject} from "aurelia-framework"; import {MovieServi ...

Restrict Angular 2 Component to specific ancestor Component

Is it possible in Angular 2 to restrict a Component so that it can only appear within a specific parent element on a page? In other words, the Component should only be allowed if it has a certain parent element. Here is an example: Allowed: <parent> ...

Setting the main color in Vue based on certain conditions

After developing a Vue app as a reusable library and setting the global $brand-color variable in the SCSS file to define the main color theme of the app, I encountered an issue when trying to integrate it for a new client who required a different brand col ...

Conceal the div element if the value is either undefined or empty in AngularJS

I am experiencing an issue where I get 2 different values when I use console.log($scope.variable). The values shown are undefined and ''. Based on this value, I need to hide a div. Here's what I have tried: <div ng-hide="$scope.variable ...

show certain DIVs based on the URL

Is it possible to dynamically display different sections based on the URL? My event website has 3 subevents, and I'd like to show the date of each event in the navigation bar for their respective URLs. <div id="us" class="us-web-date">&nbs ...

Using Filters in VueJs

I am currently working on creating a small Vue.js 2.0 application where I am utilizing the v-select component from here. The data format that I am dealing with looks something like this: { "model": [ { "id":1, ...

When an image in AngularJS is clicked, it should display a corresponding list

I'm brand new to Angular development. This is my very first solo project. My goal is to design a page where clicking on an image will display a list of items below it. For example, check out this link for reference: I've searched online for so ...

What is the most efficient method for creating around 500 small images, using either JavaScript or server-side C?

Embarking on my initial endeavor to create images dynamically. The goal is to present approximately 500 small images, each 32px X 24px in size with 16 colors, placed within table cells. Each image consists of a 2D array of colored pixels, with values prov ...

What steps can I take to resolve the "this is undefined" issue in VueJS?

Whenever I include the line this.$store.commit('disconnect');, it throws a "this is undefined" error. Any suggestions on how to resolve this issue? store/index.js : export const state = () => ({ log: false, user: {token: null, id: null, u ...

customizing highcharts title within a popup window

Is there a way to dynamically set the title of a Highcharts chart from an element? Check out my code snippet below: $(function () { var chart; $('#second-chart').highcharts({ chart: { type: 'bar' }, subtitle: { ...

Issue with Primeng 16: carousel styles failing to load properly

I am working on a straightforward project using Angular and Primeng 16. Currently, I have implemented a carousel, and everything seems to be working fine. However, when I try to navigate using the next or prev buttons, the information does not load. I ha ...

Triggering an Angular AJAX call by selecting a radio button

I am currently working on implementing a CRUD functionality in my app for the admin console. My tech stack includes MongoDB, Spring, Bootstrap, and Angular. The interface consists of a list of radio buttons on the left side containing names of collections ...