app .directive('ngNestable', function () { var ordby = 0; var recursive = function (list, parent_id) { var items = []; angular.forEach(list, function (elem) { ordby++; elem.$scope.$parent.item.orderby = ordby; elem.$scope.$parent.item.parent_id = parent_id; delete elem.$scope.$parent.item.children; if (elem.children) { elem.$scope.$parent.item.children = recursive(elem.children, elem.$scope.$parent.item.id); } items.push(elem.$scope.$parent.item); }); return items; }; return { templateUrl: '/_module/admin/views/templates/nestable.html', restrict: 'A', scope: { itemTemplateUrl: '@ngItemTemplateUrl', model: '=ngModel' }, require: 'ngModel', link: function (scope, element, attrs, ngModelCtrl) { if (!ngModelCtrl) return; scope.$watch("model", function (value) { scope.items = value; }); if (!angular.isUndefined(attrs.ngOnSorted)) { scope.onSorted = scope.$parent.$eval(attrs.ngOnSorted); } if (!angular.isUndefined(attrs.ngOnCheckbox)) { scope.onCheckbox = scope.$parent.$eval(attrs.ngOnCheckbox); } if (!angular.isUndefined(attrs.ngRemove)) { scope.remove = scope.$parent.$eval(attrs.ngRemove); } scope.collapseAll = function () { $(element).nestable('collapseAll'); }; scope.expandAll = function () { $(element).nestable('expandAll'); }; $(element) .addClass("dd") .nestable('serialize') .on('change', function ($event) { scope.$apply(function () { read($event); }); }); function read($event) { if (!angular.element($event.target).hasClass('dd')) { return; } ordby = 0; var list = $(element).nestable('serialize'); var items = recursive(list, 0); ngModelCtrl.$setViewValue(items); scope.items = angular.copy(items); if (!angular.isUndefined(scope.onSorted)) { scope.onSorted($event); } } } }; });