在angular.js指令中使用JSPlumb

时间:2015-03-06 17:46:10

标签: angularjs jsplumb

我试图将jsPlumb与AngularJS一起使用并遇到一些问题。我从github开始使用jsplumb-ng示例,并尝试修改jsPlumb参数以模仿jsPlumb站点的statemachine演示。 jsplumb-ng方法创建了一个jsPlumbCanvas指令,它包含jsPlumbNodes。作为起点,我尝试从状态机演示中放置一些静态节点,然后添加由角度控制器控制的两个节点。演示节点正确放置在画布上并创建连接。创建角度节点并且jsPlumb在makeTarget方法中出现问题并将消息输出到控制台。

TypeError:无法设置属性' _jsPlumbTarget'未定义{stack:(...),message:"无法设置属性' _jsPlumbTarget'未定义"}

我非常感谢任何建议再次前进!

事先道歉,因为我没有足够的声誉来发布问题的图像。

i.imgur.com/Ao4qzm9.png
i.imgur.com/OMS0FGE.png

Plunk

的index.html

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
    <link href="https://code.jquery.com/ui/1.11.3/themes/smoothness/jquery-ui.css" rel="stylesheet">
    <link data-require="bootstrap@3.3.1" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />

    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="https://jsplumbtoolkit.com/css/jsplumb.css" />
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.14/angular.js" data-semver="1.3.14"></script>
    <script data-require="jquery@*" data-semver="2.1.3" src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
    <script src="https://code.jquery.com/ui/1.11.3/jquery-ui.js"></script>

    <script data-require="bootstrap@3.3.1" data-semver="3.3.1" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>


    <script data-require="jsplumb@*" data-semver="1.7.3" src="https://jsplumbtoolkit.com/js/jquery.jsPlumb-1.7.3-min.js"></script>

    <script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.12.0.min.js"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="DiagramEditorCtrl">

<div id="diagramView" style="overflow: hidden;" ng-cloak>

      <js-plumb-canvas
      on-connection="onConnection1"
      x="posx"
      y="posy"
      zoom="zoomlevel"
      ng-drop="true"
      ng-drop-success="onDropComplete1($data,$event)"
      >

      <div ng-repeat="state in stateObjects track by state.uuid">
        <js-plumb-node state-object="state" style="positon: relative;"></js-plumb-node>
      </div>

      <js-plumb-connection ng-click="setActiveConnection($index)" ng-repeat="connection in stateConnections" ng-model="connection">
      </js-plumb-connection>
    </js-plumb-canvas>

</div>
  </body>

</html>

app.js

var app = angular.module('plunker', []);

app.controller('DiagramEditorCtrl', ['$scope',
function($scope) {

  $scope.zoomlevel = 85;
  $scope.posx = 14;
  $scope.posy = 14;

  $scope.stateObjects = [{
    'name': 'jsPlumb',
    'uuid': '123',
    'style': '',
    'x': 300,
    'y': 150
  }, {
    'name': 'Brewer',
    'uuid': '124',
    'style': '',
    'x': 45,
    'y': 175
  }
];


// Defaults the connections between objects.  Will come from a service.
$scope.stateConnections = [
  // {
  //    targetUUID: 'ds1',
  //    sourceUUID: 'sn1'
  // }

];

var instance = jsPlumb.instance;


$scope.onConnection = function(instance, connection, targetUUID,
  sourceUUID) {
    $scope.stateConnections.push({
      'targetUUID': targetUUID,
      'sourceUUID': sourceUUID,
      'conn': connection
    });
    $scope.$apply();

  };

}
])

.directive('jsPlumbCanvas', function() {
  var jsPlumbZoomCanvas = function(instance, zoom, el, transformOrigin) {
    transformOrigin = transformOrigin || [0, 0];
    var p = ['webkit', 'moz', 'ms', 'o'],
    s = 'scale(' + zoom + ')',
    oString = (transformOrigin[0] * 100) + '% ' + (transformOrigin[1] *
      100) +
      '%';
      for (var i = 0; i < p.length; i++) {
        el.style[p[i] + 'Transform'] = s;
        el.style[p[i] + 'TransformOrigin'] = oString;
      }
      el.style.transform = s;
      el.style.transformOrigin = oString;
      instance.setZoom(zoom);
    };

    var def = {
      restrict: 'E',
      scope: {
        onConnection: '=onConnection',
        zoom: '=',
        x: '=',
        y: '='
      },
      controller: function($scope) {
        this.scope = $scope;
      },
      transclude: true,
      templateUrl: 'workspace.html',



      link: function(scope, element, attr) {


        angular.element(document).ready(function () {


          var instance = jsPlumb.getInstance({
            Endpoint : ['Dot', {radius:2}],
            HoverPaintStyle : {strokeStyle:'#1e8151', lineWidth:2 },
            ConnectionOverlays : [
              [ 'Arrow', {
                location:1,
                id:'arrow',
                length:14,
                foldback:0.8
              } ],
              [ 'Label', { label:'Connecting...', id:'label', cssClass:'aLabel' }]
            ],
            Container:'workspace-container'
          });
          scope.jsPlumbInstance = instance;


          /*
          * Standard JSPlumb Statemachine example that works fine.
          */

          var windows = jsPlumb.getSelector('.workspace-container .node');


          instance.draggable(windows);
          instance.bind('click', function(c) {
            instance.detach(c);
          });

          instance.bind('connection', function(info) {
            info.connection.getOverlay('label').setLabel(info.connection.id);
          });

          instance.doWhileSuspended(function() {
            var isFilterSupported = instance.isDragFilterSupported();
            if (isFilterSupported) {
              instance.makeSource(windows, {
                filter:'.ep',
                anchor:'Continuous',
                connector:[ 'StateMachine', { curviness:20 } ],
                connectorStyle:{ strokeStyle:'#5c96bc', lineWidth:2, outlineColor:'transparent', outlineWidth:4 },
                maxConnections:5,
                onMaxConnections:function(info, e) {
                  alert('Maximum connections (' + info.maxConnections + ') reached');
                }
              });
            }
            else {
              var eps = jsPlumb.getSelector('.ep');
              for (var i = 0; i < eps.length; i++) {
                var e = eps[i], p = e.parentNode;
                instance.makeSource(e, {
                  parent:p,
                  anchor:'Continuous',
                  connector:[ 'StateMachine', { curviness:20 } ],
                  connectorStyle:{ strokeStyle:'#5c96bc',lineWidth:2, outlineColor:'transparent', outlineWidth:4 },
                  maxConnections:5,
                  onMaxConnections:function(info, e) {
                    alert('Maximum connections (' + info.maxConnections + ') reached');
                  }
                });
              }
            }
          });


          instance.makeTarget(windows, {
            dropOptions:{ hoverClass:'dragHover' },
            anchor:'Continuous',
            allowLoopback:true
          });



          instance.connect({ source:'opened', target:'phone1' });
          instance.connect({ source:'phone1', target:'phone1' });


          jsPlumb.fire('jsPlumbDemoLoaded', instance);


          /*
          * End standard JSPlumb statemachine example
          */
        });
      }


    };

    return def;
  })

  .directive('jsPlumbNode', function() {
    var def = {
      restrict: 'E',
      require: '^jsPlumbCanvas',
      scope: {
        node: '=stateObject'
      },

      // At one point, I tried to have a real uuid assigned as the div#id, but
      // JSPlumb seemed to see {{node.uuid}}
      // id="{{node.uuid}}"
      template: '<div class="node" ' +
      ' ng-style="{ \'left\':node.x, \'top\':node.y }" >' +
      '  <div id="ds1-nh" class="node-header" ></div>' +
      '  <div id="ds1-nb" class="node-body">' +
      '{{node.name}}' +
      '  </div>' +
      '  <div id="ds1-nt" class="node-tools">' +
      '    <div id="ds1-nt-o" class="node-tool-options">' +
      '      <span ng-click="configure($index)" class="glyphicon glyphicon-cog"></span>' +
      '    </div>' +
      '    <div id="ds1-nt-d" class="node-tool-delete">' +
      '      <span ng-click="trash($index)" class="glyphicon glyphicon-trash"></span>' +
      '    </div>' +
      '  </div>' +
      '</div>',
      link: function($scope, element, attrs, jsPlumbCanvas) {

        // removed dependence on uuid4 for this plunker.
        $scope.node.uuid = '1234-123-1233';

        angular.element(document).ready(function () {

          var instance = jsPlumbCanvas.scope.jsPlumbInstance;



          function displayMaxConnectionError(info, e) {
            alert('Maximum connections (' + info.maxConnections +
            ') reached');
          }

          var nodeEl = element.find('.node' );


          instance.draggable( nodeEl, {
            grid: [20, 20],
            drag: function(event, ui) {
              var posX, posY;
              if( typeof event.pos !== 'undefined') {
                posX = event.pos[0];
                posY = event.pos[1];
              }
              if (typeof ui !== 'undefined') {
                posX = ui.position.left;
                posY = ui.position.top;
              }
              $scope.node.x = posX;
              $scope.node.y = posY;
              $scope.$apply();
            }
          });


          // suspend drawing and initialise.
          instance.doWhileSuspended(function() {
            var eps =  element.find('.node-header');
            //console.log(eps);

            for (var i = 0; i < eps.length; i++) {
              var e = eps[i],
              p = e.parentNode;
              console.log( 'e: %o', e );
              console.log( 'e.parent: %o', p );
              instance.makeSource(e, {
                parent: p,
                anchor: 'Continuous',
                connector: ['StateMachine', {
                  curviness: 20
                }],
                connectorStyle: {
                  strokeStyle: '#5c96bc',
                  lineWidth: 2,
                  outlineColor: 'transparent',
                  outlineWidth: 4
                },
                maxConnections: 5,
                onMaxConnections: displayMaxConnectionError
              });
            }



            instance.makeTarget(nodeEl, {
              dropOptions: {
                hoverClass: 'dragHover'
              },
              anchor: 'Continuous',

              allowLoopback: true
            });
          });

        });
      }
    };
    return def;
  })






  .directive('jsPlumbConnection', function($timeout) {

    var def = {
      restrict: 'E',
      require: '^jsPlumbCanvas',
      scope: {
        ngClick: '&ngClick',
        ngModel: '=ngModel'
      },
      link: function($scope, element, attrs, jsPlumbCanvas) {
        var instance = jsPlumbCanvas.scope.jsPlumbInstance;


        $timeout(function() {

          if (typeof $scope.ngModel.conn === 'undefined') {

            $scope.ngModel.conn = instance.connect({
              uuids: [
                $scope.ngModel.targetUUID,
                $scope.ngModel.sourceUUID
              ],
              overlays: [
                ['Label', {
                  label: '',
                  id: 'label'
                }]
              ],
              editable: true
            });
          }

          var connection = $scope.ngModel.conn;


          connection.bind('mouseenter', function(conn, originalEvent) {
            $scope.ngModel.mouseover = true;
            $scope.$apply();
          });
          connection.bind('mouseleave', function(conn, originalEvent) {

            $scope.ngModel.mouseover = false;
            $scope.$apply();
          });


        }, 1300);


        $scope.$on('$destroy', function() {
          instance.detach($scope.ngModel.conn);
        });

      }
    };
    return def;
  })

  ;

我还从github查看了mrquincle / jsplumb-example。它工作正常,直到我尝试加载jsPlumb,jquery,jquery-ui和angular的更新版本。更新库的问题是两个节点之间没有连接连接。

i.imgur.com/VLtjWFy.png

Plunk

我不依赖于jsplumb-ng或jsplumb-example方法。我只想让一个人上班。

提前致谢!

0 个答案:

没有答案