react-diagrams icon indicating copy to clipboard operation
react-diagrams copied to clipboard

Deserialization doesn't register listeners on model, ports, nodes, links, etc.

Open jacobnosal opened this issue 4 years ago • 8 comments

I am having a problem with serializing => deserializing a model. After the deserialization, the listeners on each node, link, model, etc are not firing anymore. The model, ports, and links are custom and don't include code to register the listeners on instantiation.

What I am trying to accomplish is saving the diagram to a redux store (as a string, currently) to persist between visits to the site. This woks in terms of the rendering of the model, but listeners are important. I have thought about moving the listeners to constructor arguments in the factories for the custom elements. Then I can register at instantiation.

Is there a preferred way to accomplish this? The model is a string and here is an example of the deserialization process:

const model = this.props.model;
if (model) {
      const engine = this.getEngine();
       engine.getModel().deserializeModel(JSON.parse(model), engine);
 }

jacobnosal avatar Feb 05 '20 14:02 jacobnosal

+1

yossicahen avatar Mar 24 '20 15:03 yossicahen

This is because you are adding the listeners on run-time. So during deserialization, those listeners are not added I also faced the same problem, the solution is to add the listeners to the constructor of the model.

export class DiamondNodeModel extends NodeModel {
  constructor(props) {
    super("diamond");
    this.addListener({
      selectionChanged: function (e) {
        console.log("new sele", e);
      },
    });
  }
}

ishraklancer avatar Aug 05 '20 06:08 ishraklancer

I have a BaseLinkModel with the following constructor:

	constructor() {
		console.log("BaseLinkModel constructor");

		super({
			type: "base-link-model",
		});

		this.registerListener({
			sourcePortChanged: () => {
				console.log("sourcePortChanged");
			},

			targetPortChanged: () => {
				console.log("targetPortChanged");
			},

			selectionChanged: () => {
				console.log("selectionChanged");
			},

			entityRemoved: () => {
				console.log("entityRemoved");
			}
		});
	}

I have a custom port model which uses my custom link model (by overrriding createLinkModel()). I also have a custom node model, which uses my custom port model (by creating, inside the constructor, all the ports that I need).

I see the sourcePortChanged being triggered on any newly created nodes, but it doesn't get triggered on the nodes that were deserialized.

alexandernst avatar Aug 08 '20 18:08 alexandernst

Just to add some more info for further debugger. I do see the "BaseLinkModel constructor" message when I deserialize models, but I don't see the events firing.

alexandernst avatar Aug 08 '20 18:08 alexandernst

I made some progress on this. It seems that after deserializing the diagram, Nodes are using the default ports / links, instead of my custom ports / links. I'll try to find out why this is happening.

alexandernst avatar Aug 09 '20 11:08 alexandernst

I found out the issue. It turns out that my Port model didn't have a type (id string). Because of that, when I was creating new models everything was working "fine", but as soon as I serialized and then deserialized my diagram, react-diagrams was creating Ports using the DefaultPortModel instead of my CustomPortModel.

alexandernst avatar Aug 09 '20 12:08 alexandernst

This is already solved? @alexandernst

kobajs avatar Feb 02 '21 23:02 kobajs

Any updates on this issue??

haridebl3 avatar Sep 30 '21 13:09 haridebl3