JSFiddle - React, Tailwind, and code Playground

by Nicolas Lips

HTML

<script src="https://marceljuenemann.github.io/angular-drag-and-drop-lists/angular-drag-and-drop-lists.js"></script>
<div ng-app="app">
  <div ng-controller="sectionsController as ctrl">
    <ul dnd-list="ctrl.getSections()" dnd-allowed-types="['section']">
      <li ng-repeat="section in ctrl.getSections()"
      dnd-draggable="section"
          dnd-type="'section'"
          dnd-moved="ctrl.getSections().splice($index, 1)">
        <div>
          {{section.name}}
          <button ng-click="ctrl.deleteSection(section)">Delete</button>
        </div>
        <ul dnd-list="section.widgets" dnd-allowed-types="['widget']" class="widgets">
          <li ng-repeat="widget in section.widgets"
          dnd-draggable="widget"
          dnd-type="'widget'"
          dnd-moved="section.widgets.splice($index, 1)"
          class="widget">
            {{widget.name}}
            <button ng-click="ctrl.deleteWidget(widget)">Delete</button>
          </li>
        </ul>
            <button ng-click="ctrl.addWidget(section)">Add</button>      </li>
    </ul>
  <button ng-click="ctrl.addSection()">Add</button> 
  </div>
</div>

CSS

ul.widgets {
  border: 2px solid red;
  margin: 5px;
  padding: 5px
}
li.widget {
  display: block;
}

JavaScript

angular.module('app', ['dndLists'])
.service('backend', ['$timeout', function($timeout) {
	var sections = [];
  var nextSectionId = 1;
  var server = {
  	getSections: function() {
    	return init.then(function() {
      	return JSON.stringify(sections);
      });
    },
    addSection: function() {
    	$timeout(addSection, 1000);
    },
    addWidget: function(sectionName) {
    	$timeout(function() {
    		var section = getSection(sectionName)
    		addWidget(section);
       }, 1000);
    },
  };
  function getSection(name) {
  	for (var i=0;i<sections.length;i++) {
    	var section = sections[i];
      if (section.name == name) {
      	return section;
      }
    }
    return null;
  }
  function addSection() {
    var sectionId = nextSectionId++;
    var section = {
      name: "Section#"+sectionId,
      widgets: [],
      nextWidgetId: 1
    };
    sections.push(section);
    return section;
  }
  function addWidget(section) {
    var widgetId = section.nextWidgetId++;
    var widget = {
      name: section.name+"."+widgetId
    };
    section.widgets.push(widget);
    return widget;
  }
  var init = $timeout(function() {
    for (var i=0;i<3;i++) {
      var section = addSection();
      for (var j=0;j<3;j++) {
        addWidget(section);
      }
     }
     }, 1000);
  return server;
}])
.service('dataService', ['backend', function(backend) {
	var sections = [];
  backend.getSections().then(function (sectionsStr) {
  	angular.copy(JSON.parse(sectionsStr), sections);
  });  
  return {
  	getSections: function() {
    	return sections;
    },
    addSection: function() {
    	return backend.addSection();
    },
    addWidget: function(section) {
    	return backend.addWidget(section.name);
    }
  }
}])
.controller('sectionsController', ['dataService', function(dataService) {
	var vm = this;
  vm.getSections = function() {
  	return dataService.getSections();
  };
  vm.addSection = function() {
  	debugger;
  	return dataService.addSection();
  };
 ...