sagalbot / vue-sortable

A lightweight directive for reorderable drag-and-drop lists using RubaXa/Sortable
http://sagalbot.github.io/vue-sortable/
MIT License
721 stars 104 forks source link

Events not firing #4

Closed eberkund closed 8 years ago

eberkund commented 8 years ago

Am I doing something wrong? The events listed in the RubAxA/Sortable documentation do not seem to work.

<template>
<ul class="list-group" v-sortable="options">
    <li class="list-group-item">Foo <i class="handle"></i></li>
    <li class="list-group-item disabled">Bar <i class="handle"></i></li>
    <li class="list-group-item">Baz <i class="handle"></i></li>
</ul>
</template>

<script>
export default {
    data() {
        return {
            options: {
                handle: '.handle',
                filter: '.disabled',
                onStart: function (event) {
                    console.log('onStart fired'); // Never happens
                }
            }
        }
    }
}
</script>
sagalbot commented 8 years ago

I copy/pasted your code into the sortable demo site and it works exactly as expected. As soon as a drag is started, the console outputs onStart fired.

Are you getting any errors in the console? Is everything else working as expected?

eberkund commented 8 years ago

My mistake, I put the wrong code. This is what I have that is not working, is there something different I need to do if it is not a separate component? This is all on an HTML page:

<ul class="list-group" v-sortable="options">
    <li class="list-group-item">Foo <i class="handle"></i></li>
    <li class="list-group-item disabled">Bar <i class="handle"></i></li>
    <li class="list-group-item">Baz <i class="handle"></i></li>
</ul>

<script>
 new Vue({
    data: {
        options: {
            handle: '.handle',
            filter: '.disabled',
            onStart: function (event) {
                console.log('onStart fired'); // Never happens
            }
        }
    }
});
</script>
sagalbot commented 8 years ago

It looks like you're not binding your Vue instance to anything. You need to add the el parameter to your Vue instance:

 new Vue({
    el: 'body',
    data: {
        options: {
            handle: '.handle',
            filter: '.disabled',
            onStart: function (event) {
                console.log('onStart fired'); // Never happens
            }
        }
    }
});
eberkund commented 8 years ago

I have that, except I was using the ID of the table. I tried changing it to body but it didn't make a difference. Also everything else is working on the page even the other options for sortable that I have set like handle and filter

Full file:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Objex Camera Control</title>
  <link href="./css/main.css" rel="stylesheet">
</head>

<body>
  <div class="container-fluid">
    <h2>Render Queue</h2>

    <button id="protocol-handler" class="btn">Launch Agisoft</button>
    <button id="trigger" class="btn btn-danger">Trigger</button>
    <button id="focus" class="btn">Focus</button>

    <table class="table sortable" id="render-table" xmlns:v-on="http://www.vuejs.org">
      <thead>
        <tr>
          <th></th>
          <th>Render ID</th>
          <th>Customer Folder</th>
          <th>Progress</th>
          <th>Status</th>
          <th>Controls</th>
        </tr>
      </thead>

      <tbody v-sortable>
        <tr v-for="render in renders" >
          <td><i class="fa fa-arrows handle"></i></td>
          <td><a v-text="render.id" v-bind:href="'/render/' + render.id + '/edit'"></a></td>
          <td v-text="render.path"></td>
          <td v-text="render.progress + ' / 4'"></td>
          <td><span class="label {{ labelClass(render.status) }}" v-text="render.status"></span></td>
          <td>
            <i v-on:click="openPath(render.path)" class="fa fa-fw fa-folder-open"></i>
            <i class="fa fa-fw fa-pencil"></i>
            <i class="fa fa-fw fa-play"></i>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</body>

<script>
  require('./render.js');
  const Vue = require('vue');
  const $ = require('jquery');
  const Sortable = require('vue-sortable');
  const Process = require('child_process');

  Vue.use(Sortable);

  new Vue({
    el: 'body',

    data: {
      timestamp: null,
      renders: {},
      options: {
        handle: '.handle',
        filter: '.disabled',
        onStart: function () {
          console.log('test');
        }
      }
    },

    onStart: function (event) {
      console.log('test');
    },

    methods: {
      loadData: function () {
        $.getJSON('http://objex-laravel.local/api/render?api_token=RemA1xl5fCQB3cG117MnZKOfB7nYkmTQdIhLd2LjgRErqjKFYGoeVUG3r22Q', function (response) {
          if (response.timestamp <= this.timestamp) {
            return;
          }

          this.timestamp = response.timestamp;
          this.renders = response.data;
        }.bind(this));
      },

      openPath: function (path) {
        console.log('clicked a control' + path);

        Process.exec(`start ${path}`);
      },

      labelClass: function (status) {
        switch (status) {
          case 'processing': return 'label-primary';
          case 'awaiting-feedback': return 'label-warning';
          case 'complete': return 'label-success';
          case 'error': return 'label-danger';
          default: return 'label-default';
        }
      }
    },

    ready: function () {
      setInterval(() => {
        this.loadData();
      }, 2000);
    },

  });

</script>
</html>
sagalbot commented 8 years ago

I'm not sure where the issue is occurring in your case. I did up a quick fiddle and the onStart callback is being run on table rows: http://jsbin.com/vitamiq/edit?js,console,output

eberkund commented 8 years ago

Thanks so much for the help, after looking at your snippet I found that this part was different

<tbody v-sortable>

Should be

<tbody v-sortable="options">
sagalbot commented 8 years ago

Oh man, can't believe I didn't spot that! No problem, glad it's sorted.