Я делаю инструмент для создания панели инструментов. Панель инструментов состоит из строк, в каждой строке есть поля. Поэтому я пытаюсь составить список списков элементов. Элементы могут перемещаться между списками. Списки можно сортировать между собой. Все сохраняется в одном объекте, который можно легко экспортировать в формате JSON. Прохладно.
_________ ______________
| A B | move | A B C C |
|-------| C up |------------|
| C | ===> | |
|_______| |____________|
Если я перемещаю блок C в первую строку и вызываю перерисовку, блок C дублирует себя. Один C - это оригинальный ящик из второго ряда, а второй C ящик создан мифрилом из модели.
Дело в том, что я хочу просто переместить поле между строками, а не копировать его.
Я пробовал играть с onbeforeupdate и m.redraw(), но это не решение, потому что мне нужен рабочий цикл перерисовки.
class Grid {
private boxMap = new Map<TDashboardBox, IEditor>();
constructor(
public readonly dashboard: DashboardDAO,
private readonly editorFactory: IBoxFactory
) {
for (const row of dashboard.dashboard.config) {
for (const box of row) {
this.boxMap.set(box, editorFactory.create(box.title, box))
}
}
}
public boxView(box: TDashboardBox): Vnode {
return m(this.boxMap.get(box) || null);
}
public rowView(row: TDashboardRow): Vnode[] {
return row.map(b => m('.Box', {}, this.boxView(b)));
}
public view(): Vnode {
return m('.Grid', {},
this.dashboard.dashboard.config.map(r => m('.Row', {}, this.rowView(r)))
);
}
public oncreate(vnode: VnodeDOM): void {
Sortable.create(<HTMLElement>vnode.dom, {
group: "rows",
animation: 150,
onEnd: (e: SortableEvent) => {
this.dashboard.swapRows(e.oldIndex, e.newIndex);
},
});
const rows = vnode.dom.getElementsByClassName('Row');
for (let i = 0; i < rows.length; i++)
{
const row = <HTMLElement>rows[i];
Sortable.create(row, {
group: "boxes",
animation: 150,
onEnd: (e: SortableEvent) => {
const children = e.from.parentElement.childNodes;
// Search row indexes of "from row" and "to row"
let fromIndex, targetIndex;
for (let j = 0; j < children.length; j++) {
if (children[j] === e.from) {
fromIndex = j;
}
if (children[j] === e.to) {
targetIndex = j;
}
if (fromIndex !== undefined && targetIndex !== undefined) {
break;
}
}
this.dashboard.moveBox(fromIndex, e.oldDraggableIndex, targetIndex, e.newDraggableIndex);
m.redraw();
},
});
}
}
}
ИЗМЕНИТЬ 1
Скопированное поле может быть удалено в обратном вызове onEnd(). Это решает проблему копирования.
Если я поменяю местами блоки в одной строке, они поменяются местами в модели. Но на экране после перерисовки они меняются местами обратно.
ИЗМЕНИТЬ 2
Я нашел решение какое-то решение. Это почти там.
// End of onEnd() event
// if boxes moved, then...
m.render(vnode.dom, m(this)); // redraw Grid scratch
Я просто выбрасываю весь HTML-код Grid и позволяю мифрилу восстановить его.
Но сейчас в Grid просто HTML без событий, без цикла перерисовки.