HTML拖放可排序表格

12

您是否曾经想过拥有一个HTML的可拖放排序表格,可对行和列进行排序?我知道这是我为之奋斗的。现在有很多可排序的列表,但似乎找不到可排序的表格。

我知道使用script.aculo.us提供的工具可以接近实现,但我遇到了一些跨浏览器的问题。

9个回答

24

我已经成功地使用了jQuery UI的sortable插件。标记类似于这样:

<table id="myTable">
<thead>
<tr><th>ID</th><th>Name</th><th>Details</th></tr>
</thead>
<tbody class="sort">
<tr id="1"><td>1</td><td>Name1</td><td>Details1</td></tr>
<tr id="2"><td>2</td><td>Name1</td><td>Details2</td></tr>
<tr id="3"><td>3</td><td>Name1</td><td>Details3</td></tr>
<tr id="4"><td>4</td><td>Name1</td><td>Details4</td></tr>
</tbody>
</table>

然后在JavaScript中执行

$('.sort').sortable({
    cursor: 'move',
    axis:   'y',
    update: function(e, ui) {
        href = '/myReorderFunctionURL/';
        $(this).sortable("refresh");
        sorted = $(this).sortable("serialize", 'id');
        $.ajax({
            type:   'POST',
            url:    href,
            data:   sorted,
            success: function(msg) {
                //do something with the sorted data
            }
        });
    }
});

这将会把项的ID序列化后POST到给定的URL。接下来,该函数(在我的情况下是PHP)会在数据库中更新这些项的顺序。


如果有助于其他人-我遇到了一个问题,例子中的serialize调用返回null。当我更改ID,如Lathan在这里的答案所述时,它可以工作。不确定它是否与[tag:jquery]的版本相关。 - Hobo

5
我建议使用jQuery中的Sortables。你可以在列表项或几乎任何东西上使用它,包括表格。
jQuery非常适合跨浏览器,并且我一直推荐使用它。

2
我无法使jQuery sortable在表格中工作。它只会拖动整个表格或单个单元格,但没有基于行的拖动。 - JHollanti

4

我以前用过 dhtmlxGrid。除了其他功能外,它还支持拖放行/列、客户端排序(字符串、整数、日期、自定义)和多浏览器支持。

回复评论:

没有找到更好的替代品 - 只是离开了那个项目。 :-)


你以前用过它,这是否意味着你找到了更好的东西?我花了一些时间研究它,看起来它是我想要的一切。感谢你的帮助! - JHollanti

3

对我来说,David Heggie的回答最有用。可以稍微简洁一些:

var sort = function(event, ui) {
  var url = "/myReorderFunctionURL/" + $(this).sortable('serialize');
  $.post(url, null,null,"script");  // sortable("refresh") is automatic
}

$(".sort").sortable({
  cursor: 'move',
  axis: 'y',
  stop: sort
});

对我来说有效,使用相同的标记。


1

大多数框架(Yui、MooTools、jQuery、Prototype/Scriptaculous等)都具有可排序列表功能。对每个框架进行一些研究,选择最适合您需求的那一个。


0

如果在David Heggie的解决方案中,您发现.serialize()返回空值,请将TRs的id值设置为'id_1'而不是简单地'1'

例如:

<tr id="id_1"><td>1</td><td>Name1</td><td>Details1</td></tr>
<tr id="id_2"><td>2</td><td>Name1</td><td>Details2</td></tr>
<tr id="id_3"><td>3</td><td>Name1</td><td>Details3</td></tr>
<tr id="id_4"><td>4</td><td>Name1</td><td>Details4</td></tr>

以上将被序列化为"id[]=1&id[]=2&id[]=3"

您可以使用'=','-'或'_'代替'_'。 除了"id"之外的任何其他单词。


0

如果您不介意Java,有一个非常方便的GWT库称为 GWT-DND ,请查看在线演示,了解其强大之处。


我不介意Java,但其他人可能会 :) 但说真的,Java感觉有点沉重。 - JHollanti
4
因为想要可排序的表格而使用Java,就像用大锤钉螺丝一样过度。 - David Precious

0

我正在使用JQuery Sortable来实现这一点,但是如果您像我一样使用Vue.js,那么这里有一个解决方案,它创建了一个自定义的Vue指令来封装Sortable功能。我知道Vue draggable,但它不能按照问题HERE对表格列进行排序。要查看此操作,请CHECK THIS

JS代码

Vue.directive("draggable", {
  //adapted from https://codepen.io/kminek/pen/pEdmoo
  inserted: function(el, binding, a) {
    Sortable.create(el, {
      draggable: ".draggable",
      onEnd: function(e) {
        /* vnode.context is the context vue instance: "This is not documented as it's not encouraged to manipulate the vm from directives in Vue 2.0 - instead, directives should be used for low-level DOM manipulation, and higher-level stuff should be solved with components instead. But you can do this if some usecase needs this. */
        // fixme: can this be reworked to use a component?
        // https://github.com/vuejs/vue/issues/4065
        // https://forum.vuejs.org/t/how-can-i-access-the-vm-from-a-custom-directive-in-2-0/2548/3
        // https://github.com/vuejs/vue/issues/2873 "directive interface change"
        // `binding.expression` should be the name of your array from vm.data
        // set the expression like v-draggable="items"

        var clonedItems = a.context[binding.expression].filter(function(item) {
          return item;
        });
        clonedItems.splice(e.newIndex, 0, clonedItems.splice(e.oldIndex, 1)[0]);
        a.context[binding.expression] = [];
        Vue.nextTick(function() {
          a.context[binding.expression] = clonedItems;
        });

      }
    });
  }
});

const cols = [
  {name: "One", id: "one", canMove: false},
  {name: "Two", id: "two", canMove: true},
  {name: "Three", id: "three", canMove: true},
  {name: "Four", id: "four", canMove: true},
]

const rows = [
  {one: "Hi there", two: "I am so excited to test", three: "this column that actually drags and replaces", four: "another column in its place only if both can move"},
  {one: "Hi", two: "I", three: "am", four: "two"},
  {one: "Hi", two: "I", three: "am", four: "three"},
  {one: "Hi", two: "I", three: "am", four: "four"},
  {one: "Hi", two: "I", three: "am", four: "five"},
  {one: "Hi", two: "I", three: "am", four: "six"},
  {one: "Hi", two: "I", three: "am", four: "seven"}
]

Vue.component("datatable", {
  template: "#datatable",
  data() {
    return {
      cols: cols,
      rows: rows
    }
  }
})

new Vue({
  el: "#app"
})

CSS

.draggable {
  cursor: move;
}

table.table tbody td {
  white-space: nowrap;
}

Pug模板HTML

#app
  datatable

script(type="text/x-template" id="datatable")
  table.table
    thead(v-draggable="cols")
      template(v-for="c in cols")
        th(:class="{draggable: c.canMove}")
          b-dropdown#ddown1.m-md-2(:text='c.name')
            b-dropdown-item First Action
            b-dropdown-item Second Action
            b-dropdown-item Third Action
            b-dropdown-divider
            b-dropdown-item Something else here...
            b-dropdown-item(disabled='') Disabled action

    tbody
      template(v-for="row in rows")
        tr
          template(v-for="(col, index) in cols")
            td {{row[col.id]}}

-1

那么sorttable怎么样?它似乎很适合您的要求。

使用起来相当简单-加载sorttable Javascript文件,然后对于每个要使其可排序的表格,将class ="sortable"应用于<table>标记。

它会立即了解如何对大多数类型的数据进行排序,但如果有某些数据它不了解,您可以添加自定义排序键以告诉它如何排序。文档解释得非常清楚。


除了没有拖放之外,我需要能够按行自由排序表格,而不是按某些规则。 - JHollanti

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接