JSFiddle - React, Tailwind, and code Playground
HTML
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.0/jquery-ui.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.5.0/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.3.0/gridstack.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.3.0/gridstack.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.3.0/gridstack.jQueryUI.js"></script>
<!DOCTYPE html>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<title>Knockout.js demo</title>
<body>
<div class="container-fluid">
<h1>knockout.js Demo</h1>
<div>
<button data-bind="click: addNewWidget">Add new widget</button>
</div>
<br>
<div data-bind="component: {name: 'dashboard-grid', params: $data}"></div>
</div>
<template id="gridstack-template">
<div class="grid-stack" data-bind="foreach: {data: widgets, afterRender: afterAddWidget}">
<div class="grid-stack-item" data-bind="attr: {'id': $data.id, 'data-gs-x': $data.x, 'data-gs-y': $data.y, 'data-gs-width': $data.width, 'data-gs-height': $data.height, 'data-gs-auto-position': $data.auto_position}">
<div class="grid-stack-item-content" style="height: 50px; width: auto; left: 10px; right: 10px; cursor: move; color:white;" data-bind='text:$data.id'>
</div>
<div style="height: 100%;">
<div style="height: calc(100% - 50px); width: calc(100% -...
CSS
.grid-stack {
background: lightgoldenrodyellow;
}
.grid-stack-item-content {
color: #2c3e50;
text-align: center;
background-color: #4c4f53;
}
JavaScript
var grid = null;
var counter = 1;
ko.components.register('dashboard-grid', {
viewModel: {
createViewModel: function (controller, componentInfo) {
var ViewModel = function (controller, componentInfo) {
this.widgets = controller.widgets;
this.afterAddWidget = function (items) {
if (grid == null) {
grid = $(componentInfo.element).find('.grid-stack').gridstack({
auto: false,
disableResize: false,
cellHeight: 50
}).data('gridstack');
//For smooth dragging experience
grid.setAnimation(true);
}
var item = _.find(items, function (i) { return i.nodeType == 1 });
$(item).attr("id", items.id);
$(item).find(".grid-stack-item-content").
counter++;
grid.addWidget(item);
ko.utils.domNodeDisposal.addDisposeCallback(item, function () {
grid.removeWidget(item);
});
};
};
return new ViewModel(controller, componentInfo);
}
},
template: { element: 'gridstack-template' }
});
$(function () {
var Controller = function (widgets) {
var self = this;
this.widgets = ko.observableArray(widgets);
this.addNewWidget = function () {
this.widgets.push({
x: 0,
y: 0,
width: Math.floor(1 + 3 * Math.random()),
height: Math.floor(1 + 3 * Math.random())
// ...