我正在尝试实现一个可排序的drag-n-drop。我尝试了ng sortable和其他一些,但我有一些角落的案例,我没有设法根据自己的需求进行调整,而是决定自己做。
我有可拖动、可丢弃和主ui路由器视图/控制器的指令。
我正在将一个接受控制器中一些参数的函数(handleDrop())传递给可丢弃指令。我希望函数在从指令调用时更新主视图/控制器范围中的模型。
它运行良好,但抛出了一个$digest已在进行中的错误。
这是因为在该指令中,我用$apply包装对handleDrop()的调用,然后在handleDop内部,我用另一个$apply包裹函数的一部分。显然不正确,但这是我让它工作的唯一方法——因为除了错误之外,一切都很好。
如果我在handleDrop()中删除$apply,那么视图只会得到部分更新(例如,我在列表中附加了一个li元素,但为空-没有相应的数据。
根据类似问题的答案,我尝试用$timeout替换handleDrop()中的$apply,然后只要我不注入$timeout,它就可以工作,但这显然会引发"$timeout未定义",但它也可以工作。
如果我将$timeout注入控制器,我不会得到这样的错误(正如预期的那样),但dom没有再次正确更新。。
下面是我的指令和控制器的精简版本,我认为这是重要的部分。drop()是在要处理的html中指定的。
任何关于我做错了什么的帮助都非常感谢
指令:
app.directive('droppable', function() {
return {
scope: {
drop: '&',
bin: '='
},
link: function(scope, element) {
var el = element[0];
el.addEventListener(
'drop',
function(e) {
if (e.stopPropagation) e.stopPropagation();
var item = document.getElementById(e.dataTransfer.getData('text/plain'));
// Putting additional data into variables newStage etc
// call the passed drop function
scope.$apply(function(scope) {
var fn = scope.drop();
if ('undefined' !== typeof fn ) {
fn(item, newStage, prevStage, newIndex);
document.getElementById(someHtmlElementIdIHave).appendChild(item);
}
}
});
return false;
},
false
);
控制器:
.controller('funnelCtrl', function ($scope, $state, $http, someObject) {
$scope.handleDrop = function(item, newStage, prevStage, newIndex) {
$http.put('/api/funnel/' + item.id, {some object}).
success(function (data) {
$timeout(function(){
$scope.someObject[newStage].splice(newIndex, 0, item.optyId) ;
$scope.someObect[prevStage].splice(prevIndex,1);
});
}).
error(function (data) {alert('Error Saving');});
};
相反,如果$apply()
使用$timeout
作为应用触发器摘要,但超时会将其安排为下一个摘要进程运行,尽管我不确定您的代码是否需要它,但您不会将任何内容分配给当前$apply
中的作用域
$timeout(function(scope) {
var fn = scope.drop();
if ('undefined' !== typeof fn ) {
fn(item, newStage, prevStage, newIndex);
document.getElementById(someHtmlElementIdIHave).appendChild(item);
}
})