Сортировка таблиц с присвоением индекса
У меня есть array
объектов:
ruta: [
{ 'order': 1, 'id': 121 },
{ 'order': 2, 'id': 123 }
]
Я использую его как модель для таблицы buefy, и в то же время я использую расширение sortable.js, чтобы вручную упорядочить строки таблицы:
const createSortable = (el, options, vnode) => {
return Sortable.create(el, {
...options,
onEnd: function (evt) {
const data = vnode.context.ruta
const item = data[evt.oldIndex]
if (evt.newIndex > evt.oldIndex) {
for (let i = evt.oldIndex; i < evt.newIndex; i++) {
data[i] = data[i + 1]
}
} else {
for (let i = evt.oldIndex; i > evt.newIndex; i--) {
data[i] = data[i - 1]
}
}
data[evt.newIndex] = item
//here
for (let i = 0; i < data.length; i++) {
data[i].order = i + 1;
}
}
})
}
Таблица отображается правильно, но мне нужно обновить order
Параметр для каждой сортировки вручную, чтобы отразить реальный порядок таблицы. Например, мне нужно переместить пятую строку в начало таблицы, поэтому его order
Параметр должен быть 1, а остальные строки должны отражать 2, 3, 4 и 5.
Как вы можете видеть в коде, я пробовал:
for (let i = 0; i < data.length; i++) {
data[i].order = i + 1;
}
Потому что я хочу начать с 1 стоимости заказа. Я также попытался внести изменения в if / else
блоки:
if
data[i].order = i + 1;
else
data[i].order = i - 1;
Но это тоже не сработало. Порядок строк изменен неправильно.
1 ответ
Вы уже спрашивали об этом на испанском сайте SO, и я дал вам решение там. Я знаю, что вы уже решили проблему, но я собираюсь опубликовать другое решение для вашего вопроса, потому что оно может быть полезно для других пользователей в будущем.
Прежде всего, я уже объяснил вам, почему возникает эта проблема: если вы меняете порядок модели, изменяя значения ее индексов, Vue
не обнаружит изменения, вам нужно изменить array
по-другому, например, делая splice
, В вашем коде Vue
обнаруживает изменение только при изменении order
параметр и в этот момент список сортируется вручную, а значения каждого индекса array
изменились, поэтому представление будет обновлено неправильно:
┌───────────────┬───────────────┬──────────────────┬───────────────┐
│ Initial state │ -> Model │ Manually sorting │ -> Model │
├───────────────┼───────────────┼──────────────────┼───────────────┤
│ 1 - item 1 │ Array index 0 │ 1 - item 4 │ Array index 3 │
│ 2 - item 2 │ Array index 1 │ 2 - item 1 │ Array index 0 │
│ 3 - item 3 │ Array index 2 │ 3 - item 2 │ Array index 1 │
│ 4 - item 4 │ Array index 3 │ 4 - item 3 │ Array index 2 │
└───────────────┴───────────────┴──────────────────┴───────────────┘
Решение, которое я дал вам раньше:
const createSortable = (el, options, vnode) => {
// Copy the order property
vnode.context.data.forEach( (obj) => {obj.norder = obj.order} );
// Create an array of orders
const orders = vnode.context.data.map((obj) => obj.order);
return Sortable.create(el, {
...options,
onEnd: function (evt) {
const data = vnode.context.data;
// Update the position of the objects
orders.splice(evt.newIndex, 0, ...orders.splice(evt.oldIndex, 1));
// Change the order parameter
data.forEach((obj) => {
obj.order = orders.findIndex((n) => n === obj.norder) + 1;
});
}
});
};
Другое решение:
Другое решение - сбросить сортировку вручную после каждого перемещения и изменить array
заказ с использованием splice
, Взглянуть:
const createSortable = (el, options, vnode) => {
let order = [];
return Sortable.create(el, {
...options,
onStart: function (evt) {
// when the sort starts, store the initial order of the array
order = this.toArray();
},
onEnd: function (evt) {
// when the sort ends, set the order to the initial state
this.sort(order);
// change the order using splice
const data = vnode.context.data;
data.splice(evt.newIndex, 0, ...data.splice(evt.oldIndex, 1));
// now it is safe, you can update the order parameter
data.forEach((o, i) => {
o.order = i + 1;
});
}
});
};
Вот вам рабочий пример: https://codepen.io/elchininet/pen/MVNaON