Refreshing the diagram once when the given value for diagram.model changes

Hi, I’m creating a web app for a small university project, which draws graphs for a particular selected course, which the graph shows the course path of the course, such as what units/subjects can taken at the start, and how the units/subjects relate to each other as prerequisites and so on.

How I made my graph to work is that it dynamically creates a JSON format data, nodeDataArray and linkDataArray, for each specific selected course, after that I assigned diagram.model = go.Model.fromJson(value), as normal.

However, once a user would select a course option and the graph is generated for that course, it never changes what so ever when the user would then selected another course.

In other words, while the JSON data changes, the diagram.model is not updated to the changed data. Is there anyway which I can refresh the diagram or refresh diagram.model everytime the JSON data has changed?

I’m not a pro in GoJS, more so of a learner right now, but any form of help will be appreciated because I’m stuck on this issue for couple of days now.

If I understand your problem correctly you want to switch out the whole model with some other model?
You can just set the new model to your Diagram.model property when the JSON data is externally changed to rebuild the whole diagram or what have you tried?

I’m not sure how I can do that.
So far I’m using GoJS in an AngularJS environment so it’s in a custom directive.

I tried using if statements by comparing directly if the current model data is the same as another model data, and if it was true to will assign the diagram.model to another model data, but that didn’t work.

I also tried using the AngularJS custom directive, where you have scope: { model: ‘=goModel’} as from the AngularJS samples, and I pass the value in the HTML tag as an attribute, but even if I change the attribute it doesn’t work. The attribute/value is able to change, but the graph doesn’t redraw at all.

How you can set the Diagram.model property, is there a method for that? And if so, how do can I be able to call that in my controller.

I don’t know about AngularJS but in plain JS you can just set the model from JSON or any suitable JS object that represents the model. For example look at any example that uses the save/load model function ( Mind Map ), the load function is simply this:

function load() {
  myDiagram.model = go.Model.fromJson(document.getElementById("mySavedModel").value);
}

If you click the load button it redraws the diagram every time.

@vos is correct – just parse the JSON text and create a new model and initialize it and then assign Diagram.model.

But @Dandy mentioning Angular makes me think that you are not dealing with JSON-formatted text but with JavaScript Objects and Arrays in memory. You have some code that is modifying those Arrays and Objects, and GoJS does not notice that the data has been changed. That is correct and intentional – GoJS does not poll the data continuously to see if anything might have changed.

You are required to tell GoJS when that happens. Normally one should do as described in GoJS Using Models -- Northwoods Software. That is the most efficient way to modify models and to notify GoJS about each change.

But if code outside of your control is modifying data, you can call one or both of Diagram.updateAllRelationshipsFromData and Diagram.updateAllTargetBindings, depending on the types of data changes that you think have taken place out of your control. However doing so has two important drawbacks: it is very inefficient and it does not really support undo/redo well.

I can try to do that, but the problem is that, for my AngularJS controller script, there is a function that is responsible for creating the JSON data for GoJS to use. So if I change my select to another option, how and where do I call diagram.node.findNodeDataForKey and diagram.node.setDataProperty.

My GoJS codes are all in a custom directive, and so it’s separate from the controller functions. I don’t know how to call a function/access the diagram object in the custom directive from the controller.

I’ll try to find some solution related to AngularJS online for the mean time, but for now I’m still stuck

EDIT: Is it possible to use listeners? such as scope.$watch in the custom directive?
EDIT 2: I tried to use a listener such as this

And I check the console if it does retrieve the old and new model

It does indeed retrieve the newModel (the one on top) and the oldModel (the one below)
However there is this strange error I don’t understand? Any ideas?

Have you looked at Minimal GoJS Sample with AngularJS ?

By the way, if you have or intend to receive a free license for your project, unless you pay for support you will not be able to receive support from us.

I understand, I’ll look into the sample abit more

Is newModel instanceof go.GraphLinksModel true?

No, I checked, it’s false.
I even tried using diagram.model = go.Model.fromJson(newModel), and I see junk value in the console when I console.log(diagram.model)

EDIT: still no luck what so ever, I just cant seem to get the diagram.model to be replaced and the graph redrawn

FIX IT
Turns out it’s a diagram layout problem
I’m using page flow and from the sample the property of isInitial from, “layout: $(go.LayeredDigraphLayout, { isInitial: true, isOngoing: false, layerSpacing: 120})” was actually preventing the graph from being draw and redrawn.

I have to set the isInitial to true, not false

I’m glad you got it working, but whether Layout.isInitial is true or false would not produce the errors you got with trying to setup the Diagram.model.

In the Page Flow sample, the saved model does not have any node locations, so there are calls to both load() and layout(). But once the model is saved with node locations, the false value of Layout.isInitial prevents those saved node locations from being lost due to a layout.