I need to restrict the user interaction of certain links and elements. For example, if the user moves or deletes the item, the last state of this item will show up immediately and the graph will seem unaltered.
Ideally I am looking for a simple property that can be added when the element is created which prevents all changes to happen, e.g. isModifiable: false
.
Since I couldn't find one, I used the change
event and a not very elegant recursive solution for links (added as an answer below, now edited with an alternative and better solution).
Is there an ideal method for stopping or restricting changes to happen?
Element
/Link
restrictionI managed to solve this problem partially by modifying the events associated to the cells, e.g. for joint.dia.Link
:
change
event;change
event;So these would be:
let mylink = new joint.dia.Link({
source: sourceObj,
target: targetObj,
attrs : attrsObj
});
let mylinkClone = mylink.clone();
function restoreLink(link, changeStats) {
link.remove();
let rlink = mylinkClone.clone();
rlink.on('change', restoreLink);
rlink.addTo(graph);
}
mylink.on('change', restoreLink);
Once the user clicks the delete button, or tries to drag the link out, or anything else, there is literally no visual change.
This may not be a very elegant or high performance solution (due to repeated cloning) and I noticed during the period in which a token is sent through the link, the user is still able to delete it. But if you have very specific links/elements once they are created that you need to restrict, it's still effective.
interactive
property restrictionsThis is an alternative better way to restrict specific actions on all elements or links on the paper by using joint.Paper.prototype.options.interactive
, as suggested by Roman in another answer.
Link
sSo when the paper is instantiated, if you want all the interactions with links to be permanently restricted, you can just do:
var paper = new joint.dia.Paper({
interactive: {
useLinkTools: false,
labelMove: false,
vertexRemove: false,
vertexAdd: false
vertexMove: false,
arrowheadMove: false,
},
gridSize: 10,
drawGrid: true,
model: graph,
defaultLink: new joint.shapes.app.Link,
// other properties ....
})
Element
sIf you want to only restrict all elements' interactions, then:
var paper = new joint.dia.Paper({
interactive: {
elementMove: false,
addLinkFromMagnet: false,
},
// other properties ....
})
interactive
(high customisation)Or, if you use a function for the interactive
property value, you just
need to distinguish elements from links and then operate on them. For restricting only links interactions you just need to return false
when these are detected:
var paper = new joint.dia.Paper({
interactive: function (cellView) {
if(cellView.model instanceof joint.dia.Link) {
console.log('Link interaction');
return false;
}
else {
console.log('Element interaction of type:', cellView.model.get('type'));
return true;
}
},
// other properties ....
})
My preferred method of restriction for my specific case was simply done by identifying the links connected to certain sources and returning false
for them:
var paper = new joint.dia.Paper({
interactive: function (cellView) {
if(cellView.model instanceof joint.dia.Link) {
console.log('Link interaction');
var lSource = cellView.model.getSourceElement();
if(lSource instanceof joint.shapes.app.AwesomeShape){
// do not allow links connected to these sources to be modified
console.log(`Links with ${lSource.get('type')} sources cannot be modified!`);
return false;
}
// allow other links to be modified
return true;
}
console.log('Element interaction of type:', cellView.model.get('type'));
return true;
},
// other properties ....
})