角度绑定可拖动行为元素在角度方向的指令
问题描述:
我使用的是Angular和JSPlumb,我想绑定从jsplumb到我的元素在指令中的可拖动行为(在链接函数中使用element
)。角度绑定可拖动行为元素在角度方向的指令
现在我做这样的事情(http://jsfiddle.net/r8epahbt/):
// In the controller I define a method to get the elements
// via jquery and then make them draggable
function MyCtrl($scope, $http, $log, $timeout) {
$scope.makeWidgetsDraggable = function() {
// ISSUE: I have to use jQuery here, how can I do it the Angular way?
// I only want to make the "current" element draggable (it's wasteful to do ALL .widgets)
// How can I make only THIS element (could be passed from directive below) draggable
jsPlumb.draggable($('#canvas .widget'), { // Do this $('#canvas .widget') - the Angular Way
containment: "parent"
});
};
}
// When the value of $scope.items changes, we call scope.makeWidgetDraggable
// which will get ALL widgets and make them draggable.
// I only want to make the newly created widget draggable
myApp.directive("widgetTemplate", function($parse, $timeout) {
//...
link: function (scope, element, attrs) {
// Watch the `items` for change, if so (item added)
// make the new element(s) draggable
scope.$watch('items', function() {
$timeout(function() {
// [ISSUE] - This method uses jQuery to get `this` element (and all other elements)
// How can I do this the `angular way` - I want to make `this` element draggable
// (the one that is being rendered by this directive)
scope.makeWidgetsDraggable();
// I want to do something like this:
// But it Gives error: TypeError: Cannot read property 'offsetLeft' of undefined
/*jsPlumb.draggable(element, {
containment: "parent"
});*/
}); // $timeout
}); // $watch
},// link
//...
}
我觉得这样的事情应该工作(在指令中的链接功能):
// Gives me error (through JSPlumb Library):
// TypeError: Cannot read property 'offsetLeft' of undefined
jsPlumb.draggable(element, {
containment: "parent"
});
我做了一个工作JSFiddle,如果任何人都可以看看我真的很感激它。
所以基本上,我想找到做线11(在小提琴)
// I want to remove this jquery selector
jsPlumb.draggable($('#canvas .widget'),...)
// and do it the `Angular Way`
jsPlumb.draggable(element, ...)
// Doesn't work, gives me error:
// TypeError: Cannot read property 'offsetLeft' of undefined
答
一个更好的方式,您可以移动$scope.makeWidgetsDraggable
功能是指令的一部分link
,并将控制器从耦合到指令,因为您已通过指令的范围=
传递项目:
指令
myApp.directive("widgetTemplate", function ($parse, $timeout) {
return {
restrict: "E",
templateUrl: "widgetTemplate",
replace: true,
scope: {
items: "="
},
link: function (scope, element, attrs) {
scope.makeWidgetsDraggable = function() {
// ISSUE: I have to use jQuery here, how can I do it the Angular way?
// I only want to make the "current" element draggable (it's wasteful to do ALL .widgets)
// How can I make only THIS element (could be passed from directive line 46) draggable
jsPlumb.draggable(element, { // Do this $('#canvas .widget') - the Angular Way
containment: "parent"
});
};
// Watch the `items` for change, if so (item added), make the new element(s) draggable
scope.$watch('items', function() {
$timeout(function() {
// [ISSUE] - This method uses jQuery to get `this` element
// How can I do this the `angular way` - I want to make `this` element draggable
// (the one that is being rendered by this directive)
scope.makeWidgetsDraggable();
// I want to do something like this:
// But it Gives error: TypeError: Cannot read property 'offsetLeft' of undefined
/*jsPlumb.draggable(element, {
containment: "parent"
});*/
}); // $timeout
}); // $watch
}, // link
}
});
这是你的工作拨弄着变化:http://jsfiddle.net/r8epahbt/1/
编辑
好像我刚才前张贴了一下,该解决方案是行不通的100%,但是我会离开这个答案,以防它可能帮助其他人处理类似的情况。
我看到element
指向DOM comment后,第二条建议是将单个项目传递给指令,并为每个项目指定1个指令实例。这样,您就不必看任何变更的项目,你不需要任何超时:
变化鉴于:
<div id="canvas" class="canvas">
<div class="absolute widget" ng-repeat="item in items" id="widget{{$index}}" data-wId="{{$index}}">
<widget-template item="item"></widget-template>
</div>
</div>
通知我删除了<span ng-init="fakeAjaxCall"></span>
和移动它交给控制器。
指令
myApp.directive("widgetTemplate", function ($parse, $timeout) {
return {
restrict: "E",
templateUrl: "widgetTemplate",
replace: true,
scope: {
item: "="
},
link: function (scope, element, attrs) {
jsPlumb.draggable(element.parent(), {
containment: "parent"
});
//no need to watch for items added since an instance of the directive is used for each element.
}, // link
}
});
最后这里的更新的jsfiddle,这个时候我做了双重肯定它的工作原理。 http://jsfiddle.net/r8epahbt/10/
我喜欢这个想法,它可以帮助我进一步理解角度,但'jsPlumb.draggable(element..'仍然返回错误:'不能读取undefined'的属性'offsetLeft',我怎样才能得到如果你检查jsfiddle,它会在控制台中抛出相同的错误:http://jsfiddle.net/r8epahbt/2/(**注意**箱子不像原来的小提琴那样可以拖动) 。 – Anil
奇怪的是,当我发布的答案是工作,但现在我回来了,它不再工作。让我检查一下,我会更新我的答案。 – yvesmancera
这很奇怪,在指令中,元素指向DOM('ngRepeat')中的注释,我认为我有更好的解决方案,但需要做一些更改,准备就绪时会进行更新。 – yvesmancera