Перетаскиваемый Сортируемый Список в Метеоре
Как бы вы сделали это?
Элементы в списке могут соответствовать записям в коллекции, а их положение в списке может соответствовать полю в каждой записи (возможно, "ранг"), которое должно быть обновлено при наступлении события "стоп".
Будет ли Метеор хорошо играть с jQueryUI Sortable? Что произойдет, если несколько пользователей попытаются перетащить и отсортировать один и тот же список одновременно? Нужно ли Метеору настраивать сортировку?
5 ответов
РЕДАКТИРОВАТЬ: приведенный ниже ответ устарел, ответ @cutemachine или http://blog.differential.com/sortable-lists-in-meteor-using-jquery-ui намного ближе к уровню техники.
Короткий ответ: это не легко, если вы хотите, чтобы он был реактивным. Чтобы сделать нереактивную версию, просто оберните ваш шаблон в {{#constant}}
пометьте и подключите сортировку JQuery-UI в render
как предложил @bento.
Чтобы создать реактивную версию, вашему сортируемому виджету придется иметь дело с изменениями, происходящими в нем (подумайте о том, чтобы быть в середине перетаскивания, когда данные переупорядочиваются). Вот несколько мыслей о том, как бы вы поступили по этому поводу:
К сожалению, анимировать его будет непросто, что приведет к плохому UX. Давайте пока оставим это в стороне.
Визуализируйте элементы с чем-то вроде:
{{#each items}} {{> item}} {{/item}}
Это будет переупорядочивать себя, когда данные приходят с сервера (без анимации).
Установите каждый элемент для перетаскивания при рендеринге. Вы могли бы либо
я. Используйте что-то вроде jquery-ui draggable и подключите его
render
наitem
шаблон. У вас могут возникнуть проблемы с этим, поскольку базовый элемент может исчезнуть во время перетаскивания, если упорядочение изменится с восходящего.II. реализовать свой собственный код перетаскивания, возможно, используя библиотеку более низкого уровня.
Когда элемент перетаскивается на место, немедленно переупорядочивайте список локально (таким образом, пользователь должен видеть правильную вещь. Надеюсь, сервер примет это изменение к сведению... но давайте не будем вдаваться в подробности).
Я думаю, что есть большая потребность в таком виджете, сделанном метеорным способом. Это на моем личном радаре (но так много вещей, в том числе хороший способ изменить порядок с анимацией).
Новый движок рендеринга Meteor Blaze теперь гораздо лучше работает с jQuery. Вот короткое видео, которое показывает, как реализовать сортируемый список с помощью Meteor и jQuery-UI-sortable.
Код можно найти в репозитории Meteor на GitHub в папке примеров.
Самый последний пример сортируемых списков с Meteor и jQuery UI был опубликован в октябре 2014 года Дифференциалом:
http://differential.com/blog/sortable-lists-in-meteor-using-jquery-ui
Обратите внимание, что предыдущие решения могут не работать после перехода Meteor на шаблонизатор Blaze.
** Обновлено для 1.0
Проверьте MeteorPad: http://meteorpad.com/pad/TzQTngcy7PivnCCjk/sortable%20demo
Вот версия, которую я реализовал - очень похожая на @ tomsabin's, но не нужно поведение Collection Collection. Он работал хорошо для меня с несколькими пользователями и реагирует.
HTML(вероятно, не очень хорошая идея сделать идентификатор id таким же, как _id, я уверен, что вы найдете лучший обходной путь.)
<template name="myList">
<div class="step_list">
{{#each card}}
{{> card_template}}
{{/each}}
</div>
</template>
<template name="card_template">
<div class="card" id="{{_id}}">
<h3>{{name}}</h3>
</div>
</template>
JS
Template.myList.helpers ({
card : function () {
return Cards.find({}, {sort: {pos: 1}}
)}
})
Template.myList.rendered = function(){
$(".step_list").sortable({
items: ".card",
delay: 100,
refreshPositions: true,
revert: true,
helper: "clone",
scroll: true,
scrollSensitivity: 50,
scrollSpeed: 35,
start: function(event, ui) {
$(ui.helper).addClass("dragging");
}, // end of start
stop: function(event, ui) {
$(ui.item).removeClass("dragging");
}, // end of stop
update: function(event, ui) {
var index = 0;
_.each($(".card"), function(item) {
Cards.update({_id: item.id}, {
$set:{
pos: index++,
}
});
});
}
}).disableSelection();
}
Мне удалось реализовать перетаскиваемый, сортируемый и редактируемый список, используя jQuery UI sortable и Meteor Collection Hooks и contentEditable соответственно. Для частично работающего примера, посмотрите эту демонстрацию.
Моя реализация выглядит следующим образом (к сожалению, это не будет простой пример "подключи и работай", но я надеюсь вскоре запустить демо-версию для этого конкретного примера):
Клиент JS для перетаскивания, сохранения и сохранения:
Template.templateName.rendered = ->
Deps.autorun ->
$('#list').sortable
handle: '.handle'
stop: (event, ui) ->
_.each $(event.target).children('div'), (element, index, list) ->
Elements.update { _id: element.getAttribute('data-element-id') },
$set: position: index + 1
Несколько вещей, на которые стоит обратить внимание, я использую "ручку" для перетаскивания элемента, поскольку внутри каждого элемента есть другие кнопки и редактируемый контент. Как только пользователь перетащил элемент и уронил его на место, событие "стоп" начинается, и я обновляю каждый элемент в этом списке с новым позиционированием.
У меня также есть возможность добавлять элементы на страницу, которая будет располагаться внизу списка. В противном случае вам, вероятно, не удастся использовать пакеты Meteor Collection Behaviors и / или Mongo Counter. Тем не менее, я использовал Крюки Meteor Collection #.before.insert следующим образом:
Сбор перед крючком
@Elements.before.insert (userId, doc) ->
highestElement = Elements.findOne({},
sort: { position: -1 }
limit: 1
)
position = if highestElement? then highestElement.position else 0
doc.position = position + 1
Здесь мы просто получаем самый высокий документ, сортируя по атрибуту позиции. Если он не существует (например, первый элемент, который будет создан), то мы инициализируем позиции, чтобы начать с 1.
PS: если вы не понимаете CoffeeScript, скопируйте код в этот невероятный инструмент (Js2coffee).
Редактировать: пожалуйста, посмотрите отдельную версию здесь: демо (очень медленно на серверах Meteor) и исходный код