我试图将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
的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
我不依赖于jsplumb-ng或jsplumb-example方法。我只想让一个人上班。
提前致谢!