Sortable: Keep initial position of item

Created on 16 Jul 2018  路  11Comments  路  Source: SortableJS/Sortable

Similar to Chrome or Firefox Bookmarks Toolbar. It keeps initial position of item during dragging, showing a line at the position when item is potentially dropped.

feature

Most helpful comment

I'm also interested in this feature. Another great example for this is Notion:

Jun-03-2019 13-43-46

All 11 comments

Hey, also interested in a solution for this. I have the part when you transform the chosenClass: "sortable-chosen" and transform the element to a bar:

:host(.sortable-chosen) {
  visibility: hidden;
  height: 1px;
  position: relative;
  &::before {
    content: '';
    visibility: visible;
    border-bottom: 1px solid $primary;
    width: 100%;
    height: 0;
    position: absolute;
    top: 0;
    left: 0;
  }
}

But I can't achieve to let the item at its initial position and do the move only on dragEnd...

Thanks in advance for anyone helping on this!

I achieve something which is quite hacky but seems to work so far. I create a clone of my element and reinsert it in the DOM at the same place of the dragged element. And remove it onDragEnd. I have some issue of DOM rendering but it's because I use webcomponent. For normal DOM element this should work perfectly:

import Sortable from 'sortablejs';
import { EventEmitter } from '@stencil/core';

export function initMenuSort(el: HTMLElement, emitter: EventEmitter) {
  let persistentClone: HTMLElement = null;
  const sort = Sortable.create(el, {
    draggable: '.my-draggable',
    handle: '.drag-handle',
    filter: 'my-menu-action',
    group: { name: 'menu' },
    ghostClass: 'sortable-ghost',
    chosenClass: 'my-sortable-chosen',
    sort: true,
    onStart: (e: any) => {
      const el = e.item as HTMLMyComponentElement;
      let index = e.oldIndex;
      if (index < 0) {
        index = 0;
      }
      // @TODO el.cloneNode(true) (deep=true)
      // this cause the component to rerender and display the content <slot> twice
      // when stenciljs will be bulletproof on cloneNode(deep=true) we will have the clone properly displaying
      persistentClone = e.from.insertBefore(
        el.cloneNode(),
        e.from.children[index]
      );
      persistentClone.classList.add('my-sortable-disable');
      persistentClone.classList.remove('my-draggable');
      console.log(persistentClone);
      console.log(e);
      el.dragStart();
    },
    onEnd: (e: any) => {
      const data = {
        oldIndex: e.oldIndex,
        newIndex: e.newIndex,
        item: e.item,
        newParent: e.to,
        oldParent: e.from
      };
      const el = e.item as HTMLMyComponentElement;
      el.dragEnd();
      persistentClone.remove();
      persistentClone = null;
      emitter.emit(data);
    },
    onMove: e => {
      // If it's not draggable, we cancel the move
      if (e.related.classList.contains('my-draggable')) {
        return true;
      }
      return false;
    }
  });
  return sort;
}

Adapte the code to your case ;)

Perhaps a placeholder element option, to stay in the original position of the element?

We are having issues when sorting an item and then re-rendering a stencil component, this causes sortable to repeat the previous drag action - I am not sure why this is occurring. @Nightbr is this the issue you were trying to get around ?

Hey @miguelyoobic95 it's another problem you describe. But we manage to include sortableJS with stenciljs component, we use our fork
-> "sortablejs": "https://github.com/saloonio/Sortable.git#dev-firefoxShadowRoot"

We use a stenciljs component container which instantiate sortablejs:

componentDidLoad() {
    this.sortableElement = Sortable.create(this.el.querySelector('.components') as HTMLElement, {
      handle: '.drag-icon',
      draggable: '.plop-draggable',
      filter: 'plop-new-component-container soon-button',
      animation: 150,
      onStart: e => {
        const el = e.item as HTMLPlopComponentElement;
        el.dragStart();
      },
      onEnd: e => {
        const el = e.item as HTMLPlopComponentElement;
        el.dragEnd();
        this.drop(e);
      },
      onMove: e => {
        // If it's not draggable, we cancel the move
        if (e.related.classList.contains('plop-draggable')) {
          return true;
        }
        return false;
      }
    });
  }

I'm also interested in this feature. Another great example for this is Notion:

Jun-03-2019 13-43-46

This would be a great idea for a plugin. I could try to make it myself, but if anyone else wants to give it a try - the docs for creating a plugin are here: https://github.com/SortableJS/Sortable/blob/master/plugins/README.md

@Nightbr Would you be interested in making your implementation into a plugin?

I don't think it could be easy because I'm wrapping SortableJS into a Stenciljs webcomponent. But I could try if I have spare time ;)

Is there any plugin or API available to achieve this using just SortableJS?

I am also stuck with the same problem.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

chrishaigy picture chrishaigy  路  3Comments

graemegeorge picture graemegeorge  路  4Comments

artaommahe picture artaommahe  路  4Comments

dwburdick picture dwburdick  路  3Comments

jkrasnay picture jkrasnay  路  3Comments