javascriptjquerygridstack

How to make dynamically created elements draggable with gridstack?


In my project I'm using this drag and drop library called gridstack. You can see their documentation on github here. When you hardcode elements inside the dom and initialize the gridstack, those elements are draggable. But when the elements are created dynamically with a forloop, they are not draggable even if they have the proper draggable classes. How can I make this work?

//initialize grid stack
var grid = GridStack.init({
minRow: 5, // don't collapse when empty
cellHeight: 70,
acceptWidgets: true,// acceptWidgets - accept widgets dragged from other grids or from outside (default: false).
dragIn: '.newWidget',  // class that can be dragged from outside
dragInOptions: { revert: 'invalid', scroll: false, appendTo: 'body', helper:'clone' }, // clone or can be your function
removable: '#trash', // drag-out delete class
});

//gridstack on change
grid.on('added removed change', function(e, items) {
let str = '';
items.forEach(function(item) { str += ' (x,y)=' + item.x + ',' + item.y; });
console.log(e.type + ' ' + items.length + ' items:' + str );
});

//dynamic elemenets
const arr = ["Bruh cant drag me!", "Nope me neither", "Me too mouhahaha"];

//loop
for (let i = 0; i < arr.length; i++) {
var div = document.createElement('div');

var el = "<div class='newWidget grid-stack-item ui-draggable ui-resizable ui-resizable-autohide'> <div class='grid-stack-item-content' style='padding: 5px;'> "+arr[i]+"</div></div>";

div.innerHTML = el;
$('.dynamic').append(div);

}
.grid-stack-item-removing {
opacity: 0.8;
filter: blur(5px);
}
#trash {
background: rgba(255, 0, 0, 0.4);
padding: 5px; 
text-align: center;
}

.grid-stack-item{
background: whitesmoke;
width: 50%;
border: 1px dashed grey;

}

.grid-stack {
background : #F0FFC0;
}
<!-- jquery --> 
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<!-- gridstack--> 
<link rel="stylesheet" href="https://gridstackjs.com/node_modules/gridstack/dist/gridstack-extra.min.css"/>
<script src="https://gridstackjs.com/node_modules/gridstack/dist/gridstack-h5.js"></script>

<!-- body--> 
<body>

<div id="trash"><span>drop here to remove</span> </div>

<br>

<div class="dynamic"></div>

<div class="newWidget grid-stack-item ui-draggable ui-resizable ui-resizable-autohide">
<div class="grid-stack-item-content" style="padding: 5px;">
<div>
</div>
<div>
<span>I'm original domster! Drag and drop me!</span>
</div>
</div>
</div>

<br>

<div class="grid-stack"></div>

</body>


Solution

  • This issue was raised here. The grid does not automatically track external changes so the grid needs to be re-initialize for the dragIn option to notice the new dynamic widgets

    GridStack.setupDragIn()
    

    Full code

    //initialize grid stack
    var grid = GridStack.init({
    minRow: 5, // don't collapse when empty
    cellHeight: 70,
    acceptWidgets: true,// acceptWidgets - accept widgets dragged from other grids or from outside (default: false).
    dragIn: '.newWidget',  // class that can be dragged from outside
    dragInOptions: { revert: 'invalid', scroll: false, appendTo: 'body', helper:'clone' }, // clone or can be your function
    removable: '#trash', // drag-out delete class
    });
    
    //gridstack on change
    grid.on('added removed change', function(e, items) {
    let str = '';
    items.forEach(function(item) { str += ' (x,y)=' + item.x + ',' + item.y; });
    console.log(e.type + ' ' + items.length + ' items:' + str );
    });
    
    //dynamic elemenets
    const arr = ["Bruh cant drag me!", "Nope me neither", "Me too mouhahaha"];
    
    //loop
    for (let i = 0; i < arr.length; i++) {
    var div = document.createElement('div');
    
    var el = "<div class='newWidget grid-stack-item ui-draggable ui-resizable ui-resizable-autohide'> <div class='grid-stack-item-content' style='padding: 5px;'> "+arr[i]+"</div></div>";
    
    div.innerHTML = el;
    $('.dynamic').append(div);
    
    }
    GridStack.setupDragIn(
    
    '.newWidget', 
    
    );
    .grid-stack-item-removing {
    opacity: 0.8;
    filter: blur(5px);
    }
    #trash {
    background: rgba(255, 0, 0, 0.4);
    padding: 5px; 
    text-align: center;
    }
    
    .grid-stack-item{
    background: whitesmoke;
    width: 50%;
    border: 1px dashed grey;
    
    }
    
    .grid-stack {
    background : #F0FFC0;
    }
    <!-- jquery --> 
    <script src="https://code.jquery.com/jquery-3.6.0.js"></script>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    
    <!-- gridstack--> 
    <link rel="stylesheet" href="https://gridstackjs.com/node_modules/gridstack/dist/gridstack-extra.min.css"/>
    <script src="https://gridstackjs.com/node_modules/gridstack/dist/gridstack-h5.js"></script>
    
    <!-- body--> 
    <body>
    
    <div id="trash"><span>drop here to remove</span> </div>
    
    <br>
    
    <div class="dynamic"></div>
    
    <div class="newWidget grid-stack-item ui-draggable ui-resizable ui-resizable-autohide">
    <div class="grid-stack-item-content" style="padding: 5px;">
    <div>
    </div>
    <div>
    <span>I'm original domster! Drag and drop me!</span>
    </div>
    </div>
    </div>
    
    <br>
    
    <div class="grid-stack"></div>
    
    </body>