角度方式

时间:2015-08-21 16:19:10

标签: angularjs jsplumb

我使用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,如果有人可以看看我真的很感激。

http://jsfiddle.net/r8epahbt/

所以基本上,我想找到一个更好的方法来做第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

1 个答案:

答案 0 :(得分:2)

您可以将$scope.makeWidgetsDraggable函数移动到指令link的一部分,并将控制器从耦合到指令中删除,因为您已经通过指令的范围传递了项目{ {1}}:

<强>指令

=

以下是您改变的工作小提琴:http://jsfiddle.net/r8epahbt/1/

修改

似乎我之前发布了一点,并且解决方案没有100%正常工作,但是我将离开那个答案,以防它可能在类似的情况下帮助其他人。

在看到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 } }); 指向DOM comment的方式之后,我的第二个建议是将单个项目传递给指令,并且每个项目有1个指令实例。这样您就不必观察任何更改的项目,也不需要任何超时:

视野中的变化

element

注意我删除了<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>

最后这里是更新的jsfiddle,这次我确定它确实有效。 http://jsfiddle.net/r8epahbt/10/