Sortable: Feature request: allow to clone element with different output in another list

Created on 29 Dec 2016  路  11Comments  路  Source: SortableJS/Sortable

Hi,

it would be awesome if you could pull some element from a list foo and insert it in another list bar but with a different layout:

See example of what would be desired:
http://jsbin.com/fovedo/1/edit?html,css,js,output

question

Most helpful comment

This is actually quite possible.

I was looking for a lighter alternative to jQuery UI, and Sortable looked very promising. My use case is that I am building a drag and drop template editor, where users drag thumbnail representations of template modules that, when dropped in the template, pull in the module (HTML) itself.

All you need to do is use onAdd to replace the evt.item with your own HTML.
Please see this demo (excuse the use of jQuery, you can replace it with vanilla JS):

http://jsbin.com/zepasikuto/edit?html,css,js,output

All 11 comments

Alas, this is not possible.

This is actually quite possible.

I was looking for a lighter alternative to jQuery UI, and Sortable looked very promising. My use case is that I am building a drag and drop template editor, where users drag thumbnail representations of template modules that, when dropped in the template, pull in the module (HTML) itself.

All you need to do is use onAdd to replace the evt.item with your own HTML.
Please see this demo (excuse the use of jQuery, you can replace it with vanilla JS):

http://jsbin.com/zepasikuto/edit?html,css,js,output

Hi @hellocosmin.

I have a similar use case and have worked it out the same way as demonstrated by replacing the original content for the target HTML after the onAdd event.

But this falls short for my original intention. I wanted to show the resulting HTML content already during the drag event on, whereas the applied solution inserts the original content in the list, shows the original content while dragging and only shows the resulting content on the drop action.

After inspecting the Sortable source code I must admit that to have a different clone as desired would force to do a big code refactoring so I accept @RubaXa answer for now.

In addition to this, such a possibility even more strongly complicate library, easiest way adapt the html/css.

Indeed, the ghost is impossible to change as it is right now.

But would allowing for passing a DOM element/object complicate things so much? I'm thinking: if a custom ghost element was passed, use it; otherwise clone the dragged element, just as it's currently being done.

Yeah, a custom ghost would do it, even better if the custom ghost supported calling a function which in turn returned the ghost html. We both need this since we're adding module templates and need different representations for the dragged thumbnail.

@hellocosmin thanks for that example, it's just what I was looking for.

@victorhsb I think custom ghost is possible, here is my code:

        onClone: function (evt) {
            $(evt.item).css('border', '4px solid red')
            $(evt.item).html('<b> OLE </b>')
        }

as you can see you can change the css of ghost and also insert any html you want, if you insert your template html you should see that while dragging

here is image of it in action

Ghost

since you can change the css and insert any html code you like, you should be able to accomplish what you are looking for, right?

@nikocraft If I try it your way, I end up having the new element in the draggable list, and the original as dragged and dropped element...

is the solution posted above by @cossssmin still the way to control what will be displayed in the dragged list? My use case is very similar to @cossssmin 's. I think setting an item in the data list that is included in the setList call is a neat solution.

Actually this did work for me. Not sure if there are any gotchas with this approach.

  const onSetList = (list) => {
    setComponentState({
     someViewStateFields,
      listItems: getConvertedList(list),
    });
  };

const getConvertedList = (list) => {
  const dropIndex =   _.findIndex(list, (item) => {_.startsWith(item.id, 'create')});
  // if this is a regular sort just return.
  if (dropIndex === -1) {
    return list;
  }
  // otherwise replace it with initial data for the new object
  list.splice(
    dropIndex,
    dropIndex,
    { id: _.uniqueId(), field1: ..., field2:...}
  );
  return list;
};
    <ReactSortable
      group={{ name: 'core', put: ['create'] }}
      setList={onSetList}
      .....
     />
Was this page helpful?
0 / 5 - 0 ratings

Related issues

kinjal-codes picture kinjal-codes  路  3Comments

dwburdick picture dwburdick  路  3Comments

seltix5 picture seltix5  路  3Comments

geonanorch picture geonanorch  路  3Comments

rakeshrockb picture rakeshrockb  路  3Comments