2

I have a custom directive called "sortable" but I ran into a problem with the DOM. The problem is when I dragged and dropped an item the array is changed but the DOM isn't.

This is my custom directive:

 Vue.directive('sortable', {
    bind: function(el, binding, vnode) {
        // Initialize sortable
        this.sortable = Sortable.create(el, {});
        console.debug("Sortable initialized");

        this.sortable.option("onUpdate", function(event) {
            binding.value.move(event.oldIndex, event.newIndex);
            var updated = binding.value;
            Vue.set(tasks, updated);
        });
    }
});

And this is how I create my Vue instance:

app = new Vue({
    el: "#app",
    data: {
        subtotal: 0,
        tasks: [
            {name: '', quantity: '', rate: 80, costs: ''}
        ]
    },
    methods: {
        newTask: function() {
            this.tasks.push({name: '', quantity: '', rate: 80, costs: ''})
        },
        deleteTask: function(index) {
            this.tasks.splice(index, 1);
            this.calculateTotal();
        },
        calculateCosts: function(event, value, index) {
            this.tasks[index].costs = event.target.value * value;
            this.calculateTotal();
        },
        calculateTotal: function() {
            this.subtotal = 0;
            _.forEach(this.tasks, $.proxy(function(task) {
                this.subtotal += task.costs;
            }, this));
        }
    }
});

In my template I use: v-for="(task, index) in tasks". Did I something wrong?

1
  • when You drag and drop an item, which method is getting called? Commented Dec 22, 2016 at 3:42

2 Answers 2

17

As per the documentation, the following methods will trigger view updates. The wrapped methods are:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

However I see you are also doing this assignment in calculateCosts method, which will not trigger the mutation, due to caveats in vue:

this.tasks[index].costs = event.target.value * value;

This can be replaced with the following to trigger the mutation and update the view with the help of Object.assign and Vue.set:

var newVal = Object.assign({}, this.tasks[index], {costs: event.target.value * value})
Vue.set(this.tasks, index, newVal)
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your reaction. I placed this exact same question on the Laravel forum and it is fixed now. The only problem was that I forget the :key=tasks inside of the DOM. But thanks anyways.
I had a similar issue, and it was bugging me for a while. But I got it fixed because of your comment. So thank you! For future readers, it's actually :key=task instead of :key=tasks.
1

To make vue recept it, use a proper unique key from the array value, not the array index:

<!-- use value.id in :key, not index -->
<div v-for="(value, index) in values" :key="value.id"> .... </div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.