2015-08-21 84 views
2

我使用的是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 

回答

2

一個更好的方式,您可以移動$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/

+0

我喜歡這個想法,它可以幫助我進一步理解角度,但'jsPlumb.draggable(element..'仍然返回錯誤:'不能讀取undefined'的屬性'offsetLeft',我怎樣才能得到如果你檢查jsfiddle,它會在控制檯中拋出相同的錯誤:http://jsfiddle.net/r8epahbt/2/(**注意**箱子不像原來的小提琴那樣可以拖動) 。 – Anil

+0

奇怪的是,當我發佈的答案是工作,但現在我回來了,它不再工作。讓我檢查一下,我會更新我的答案。 – yvesmancera

+0

這很奇怪,在指令中,元素指向DOM('ngRepeat')中的註釋,我認爲我有更好的解決方案,但需要做一些更改,準備就緒時會進行更新。 – yvesmancera