Dynamic Sortable
Description
I have a problem with a dynamic sortable list, which elements should also be sortable. The problem is, that each element in the list is dynamic, as it will be cloned from a template div and appended to document.
Issue
Currently the blocks (.pb-row) are sortable just as expected.
But the nested sortable for the dynamically added widgets (.builder-row-content) doesn`t work.
Only nested nodes in the first block will be draggable and are very buggy. Also i can drag them outside of the row.
Nodes from additionally added Blocks are not draggable at all.
Also i receive this message in the console
cannot call methods on sortable prior to initialization; attempted to call method ‘refresh’
Code
Html to run the sortable:
<div class="pb-rows"> // Wrapper of all Blocks <div class="pb-row" name="pb-row"> // each Block <div class="builder-row-header"> <span class="row-btn pb-handle fas fa-sort"></span> <div>Block</div> <span onclick="handleRemoveClick(this)" class="row-btn row-btn-right pb-remove fas fa-trash"></span> </div> <div class="pb-container"> <div class="builder-row-content"> // nested sortable widgets will appear here </div> </div> </div> // more .pb-rows will appear here </div>
Attempt for jQuery sortable list:
// jQuery Sorting Lib jQuery(".pb-rows").sortable({ handle: ".pb-handle", cursor: "grabbing", }); // jQuery Sorting Lib jQuery(".builder-row-content").sortable({ connectWith: '.pb-rows handle: ".pb-handle-widget", cursor: "grabbing", });
Attempted solution which doesnt work:
const handleAddClick = e => { e.preventDefault(); ... jQuery(".builder-row-content").sortable("refresh"); };
Screenshot
Advertisement
Answer
You need to reinitialize sortable onto dynamically added elements, so:
Wrap your sortable events in a function
// Sorting function enableSort() { // jQuery Sorting Lib $(".pb-rows").sortable({ handle: ".pb-handle", cursor: "grabbing" }); // jQuery Sorting Lib $(".builder-row-content").sortable({ handle: ".pb-handle-widget", cursor: "grabbing" }); } enableSort();
Then call the function in pbCreateNode
.
const pbCreateNode = (type, props, html) => { enableSort(); let element = document.createElement(type); props && props.forEach(prop => { let key = Object.keys(prop)[0]; let value = prop[key]; element.setAttribute(key, value); }); html && (element.innerHTML = html); return element; };