我使用这个脚本作为我的起点:http: //jsfiddle.net/EJGHX/ 我已经修改它以从数据库构建一个列表,但我无法以服务器可以读取的格式将其发送回。
这是我的代码:
JS
var app = angular.module('app', []);
app.config(function ($routeProvider) {
$routeProvider.when('/article/:slug', {
templateUrl: '/university_assets/partials/admin/content.html',
controller: 'TreeController'
})
.when('/', {
templateUrl: '/university_assets/partials/home.html'
})
.when('/add', {
templateUrl: '/university_assets/partials/admin/addContent.html'
})
.otherwise({
templateUrl: '/university_assets/partials/404.html'
});
});
app.directive('yaTree', function () {
return {
restrict: 'A',
transclude: 'element',
priority: 1000,
terminal: true,
compile: function (tElement, tAttrs, transclude) {
var repeatExpr, childExpr, rootExpr, childrenExpr;
repeatExpr = tAttrs.yaTree.match(/^(.*) in ((?:.*\.)?(.*)) at (.*)$/);
childExpr = repeatExpr[1];
rootExpr = repeatExpr[2];
childrenExpr = repeatExpr[3];
branchExpr = repeatExpr[4];
return function link(scope, element, attrs) {
var rootElement = element[0].parentNode,
cache = [];
// Reverse lookup object to avoid re-rendering elements
function lookup(child) {
var i = cache.length;
while (i--) {
if (cache[i].scope[childExpr] === child) {
return cache.splice(i, 1)[0];
}
}
}
scope.$watch(rootExpr, function (root) {
var currentCache = [];
// Recurse the data structure
(function walk(children, parentNode, parentScope, depth) {
var i = 0,
n = children.length,
last = n - 1,
cursor,
child,
cached,
childScope,
grandchildren;
// Iterate the children at the current level
for (; i < n; ++i) {
// We will compare the cached element to the element in
// at the destination index. If it does not match, then
// the cached element is being moved into this position.
cursor = parentNode.childNodes[i];
child = children[i];
// See if this child has been previously rendered
// using a reverse lookup by object reference
cached = lookup(child);
// If the parentScope no longer matches, we've moved.
// We'll have to transclude again so that scopes
// and controllers are properly inherited
if (cached && cached.parentScope !== parentScope) {
cache.push(cached);
cached = null;
}
// If it has not, render a new element and prepare its scope
// We also cache a reference to its branch node which will
// be used as the parentNode in the next level of recursion
if (!cached) {
transclude(parentScope.$new(), function (clone, childScope) {
childScope[childExpr] = child;
cached = {
scope: childScope,
parentScope: parentScope,
element: clone[0],
branch: clone.find(branchExpr)[0]
};
// This had to happen during transclusion so inherited
// controllers, among other things, work properly
parentNode.insertBefore(cached.element, cursor);
});
} else if (cached.element !== cursor) {
parentNode.insertBefore(cached.element, cursor);
}
// Lets's set some scope values
childScope = cached.scope;
// Store the current depth on the scope in case you want
// to use it (for good or evil, no judgment).
childScope.$depth = depth;
// Emulate some ng-repeat values
childScope.$index = i;
childScope.$first = (i === 0);
childScope.$last = (i === last);
childScope.$middle = !(childScope.$first || childScope.$last);
// Push the object onto the new cache which will replace
// the old cache at the end of the walk.
currentCache.push(cached);
// If the child has children of its own, recurse 'em.
grandchildren = child[childrenExpr];
if (grandchildren && grandchildren.length) {
walk(grandchildren, cached.branch, childScope, depth + 1);
}
}
})(root, rootElement, scope, 0);
// Cleanup objects which have been removed.
// Remove DOM elements and destroy scopes to prevent memory leaks.
i = cache.length;
while (i--) {
cached = cache[i];
if (cached.scope) {
cached.scope.$destroy();
}
if (cached.element) {
cached.element.parentNode.removeChild(cached.element);
}
}
// Replace previous cache.
cache = currentCache;
}, true);
};
}
};
});
app.controller('TreeController', function ($rootScope, $scope, $timeout, $http, $location) {
$scope.data = {
children: [{
text: '',
children: []
}]
};
$http.get('/university/list').success(function (data) {
var myArr = data;
for (var i = 0; i < myArr.length; i++) {
myArr[i].children = [];
for (var q = 0; q < myArr.length; q++) {
if (myArr[i].id == myArr[q].parentid) {
var temp = {
id: myArr[q].id,
text: myArr[q].text,
index: myArr[q].index
};
myArr[i].children.push(temp);
};
};
};
$scope.data = ({
children: myArr
});
});
$scope.index = function (i, child) {
child.index = i;
}
$http.get('/university' + $location.path()).success(function (data) {
$rootScope.pageContent = data[0];
$rootScope.page = $scope.pageContent;
});
$scope.edit = function (child) {
$http.get('/university/article/' + child.id).success(function (data) {
$rootScope.pageContent = data[0];
$rootScope.page = $scope.pageContent;
});
$location.path('/article/' + child.id);
$("#article").attr("action", "/admin/updateArticle");
$('.admin-actions button').text(' Update ');
};
$scope.toggleMinimized = function (child) {
child.minimized = !child.minimized;
};
$scope.addChild = function (child) {
child.children.push({
title: '',
children: []
});
};
$scope.remove = function (child) {
function walk(target) {
var children = target.children,
i;
if (children) {
i = children.length;
while (i--) {
if (children[i] === child) {
return children.splice(i, 1);
} else {
walk(children[i])
}
}
}
}
walk($scope.data);
}
$scope.update = function (event, ui) {
var root = event.target,
item = ui.item,
parent = item.parent(),
target = (parent[0] === root) ? $scope.data : parent.scope().child,
child = item.scope().child,
index = item.index();
target.children || (target.children = []);
function walk(target, child) {
var children = target.children,
i;
if (children) {
i = children.length;
while (i--) {
if (children[i] === child) {
return children.splice(i, 1);
} else {
walk(children[i], child);
}
}
}
}
walk($scope.data, child);
target.children.splice(index, 0, child);
var graph = $scope.data.children;
console.log(graph);
var i, l,
nodes=[],
visited=[];
function clone(n) {
// improve the function yourself I'm lazy
return {
"id": n.id,
"parentid": n.parentid,
"text": n.text,
"index": n.index
};
}
function helper (node) {
var i, limit;
if (visited.indexOf(node.id) == -1) {
visited.push(node.id);
nodes.push(clone(node));
if( node.children)
for (i=0, limit = node.children.length; i< limit; i++) {
helper(node.children[i]);
}
}
}
for (i=0, l = graph.length; i< l; i++) {
helper(graph[i]);
}
nodes = JSON.stringify(nodes);
$http.post('/admin/sort/', nodes).success(function () {});
};
});
app.directive('uiNestedSortable', ['$parse', function ($parse) {
'use strict';
var eventTypes = 'Create Start Sort Change BeforeStop Stop Update Receive Remove Over Out Activate Deactivate'.split(' ');
return {
restrict: 'A',
link: function (scope, element, attrs) {
var options = attrs.uiNestedSortable ? $parse(attrs.uiNestedSortable)() : {};
angular.forEach(eventTypes, function (eventType) {
var attr = attrs['uiNestedSortable' + eventType],
callback;
if (attr) {
callback = $parse(attr);
options[eventType.charAt(0).toLowerCase() + eventType.substr(1)] = function (event, ui) {
scope.$apply(function () {
callback(scope, {
$event: event,
$ui: ui
});
});
};
}
});
element.nestedSortable(options);
}
};
}]);
除了一些添加的 $http 请求和这个之外,它基本上是相同的:
var graph = data.children;
console.log(graph);
var i, l,
nodes=[],
visited=[];
function clone(n) {
// improve the function yourself I'm lazy
return {
"id": n.id,
"parentid": n.parentid,
"text": n.text,
"index": n.index
};
}
function helper (node) {
var i, limit;
if (visited.indexOf(node.id) == -1) {
visited.push(node.id);
nodes.push(clone(node));
if( node.children)
for (i=0, limit = node.children.length; i< limit; i++) {
helper(node.children[i]);
}
}
}
for (i=0, l = graph.length; i< l; i++) {
helper(graph[i]);
}
nodes = JSON.stringify(nodes);
$http.post('/admin/sort/', nodes).success(function () {});
我需要在更新功能运行后运行它。这会展平我的 $scope.data 数组并将其发送到服务器。
我的问题是..如果我把上面的函数放在我的 $scope.update 函数中,它会在更改之前发送以前的数据。它会发送 'index': 1,当我把它移到 'index': 2 时。