Hi, I’ve got a diagram that has nested groups and a button/feature to show or hide certain types of groups.
Pressing the button should hide the group without affecting (hiding or moving) the child nodes.
Previously when using the ReactDiagram component this was trivial because the data was re-written every time and the diagram would update accordingly.
Now using GoJS manually it is not working as expected.
Hiding the group and not hiding/moving the children is easy and works well.
However, the child nodes don’t jump back into their parent group when Unhiding the group that has previously been hidden.
Screenshot #1:
Here is one group with three children, one is another group with itself one child.
Screenshot #2:
Here everything is after clicking the “hide group” button. We see the two parent groups have been hidden and the non-group children remain.
Screenshot #3:
And here is the issue, after clicking the “hide group” button again, the parent groups ARE added, but their children nodes are not inside them.
As for what the button does, it hides the specified group and changes the child “group” property to an empty string.
// Hide Parent
if (node.source === "SpecifiedGroup" && !node.isHidden) {
node.isHidden = true;
}
// Remove Child from parent group
if (
!node.isGroup &&
!node.isHidden &&
node.group &&
node.group.startsWith("SpecifiedGroup")
) {
// save the value for later
node.__originalGroup = node.group;
node.group = "";
}
If the Group does not have a Placeholder, what determines the position and size of the group?
In the button click code, is node a node data object that is in the model? If so, you need to call model methods when you modify data. For example, call Model.set when setting any data property.
The node items are node data items from the model.
At the end of the function (I didn’t include it in the snippet, sorry) set a property (node.__shouldUpdate) to true. This allows us to programmatically update only the nodes that need updating in a transaction.
The transaction code looks like this:
Basically, if the node should be updated and its group has been set to “” remove it from the group.
diagram.commit((d: Diagram) => {
d.nodes.each((node) => {
if (node?.data?.__shouldUpdate) {
const data = node?.data;
if (data.group === "") {
d.model.setDataProperty(data, "group", undefined);
}
// Update the asset's data bindings
node.updateTargetBindings();
}
});
I did some debugging last night, and I have a suspicion that the code is doing exactly what it should.
And the reason why the child nodes don’t magically reappear in their parent groups after toggling the “SpecifiedGroup” off and then on again is that they still exist in their original spot. (it is hard to tell from the screenshots but the child nodes never move or change visually, just the groups that contain them)
I may not understand all of your requirements, but my first impression is that it would be easiest if you put all of the groups that you expect to show/hide into a separate Layer. That way you can just set that layer’s Layer.visible or Layer.opacity property in order to show/hide all of those groups.
The advantage of such a scheme, or even just iterating through all of the groups (Diagram.nodes), is that it doesn’t modify the model, which I assume you would like to maintain whole no matter what you show to the user.
Hmm, I never thought of using layers for different groups, interesting.
You are correct about us not wanting to change the model (unless needed)
Question, if a group (with children) is in a layer and we change the Layer.visible or Layer.opacity do the children remain visible?
I guess my question is: are the child nodes in a group placed on the same layer as the group?
Each Part has its own Part.layerName property, and thus Part.layer value. (If a layer name doesn’t exist, it will be put into a different layer, by default the layer whose name is the empty string, “”.)
So if you have enough Layers, you could have each Node and each Group be in a different Layer. That would be an inefficient way to implement things, though. Usually the pre-defined three layers, “Background”, “”, and “Foreground” are sufficient for most purposes. GoJS Layers -- Northwoods Software
diagram.commit(d => {
var layer = d.findLayer("blue");
if (layer !== null) layer.visible = !layer.visible;
}, 'toggle ' + "blue");
The child nodes say they are on layerName “” (the default)
Am I doing something wrong, or it’s normal that the child nodes disappear when hiding their containing group even if the group is on a different level?
Thanks, that works very well and seems pretty lightweight.
The behaviour of the links is interesting when using layers.
When hiding the layer with the “SpecifiedGroup” links that connect a node on the default layer to a group on the “blue” layer are only half hidden.
See the second blue link coming from the node at the bottom, it goes halfway to where the group (which is hidden on the “blue” layer)
Ah, it is not compatible with our situation, unfortunately.
We allow the users to expand and collapse all groups (if there are any) at any time.
This becomes complicated very fast with groups that exist but are invisible with child nodes inside them.
In any case, I will keep this layer technique in mind for other things it is very slick.
Let’s say I wanted to create a function that starts an animation or something similar.
The function would expand the “SpecifiedGroup” that has just been Unhidden.
Then go find all of its children in the diagram model.
Then move them physically into the container group.
Yes, sorry the question was not clear.
When a node is rendered physically outside of its parent group. (like my third screenshot at the start of this thread)
How do I animate it moving into its parent groups?
Yes, if the group could be programmatically opened and the nodes animate or move into the group that would be ideal.
A second option could be to leave the group collapsed and have the nodes move toward the group and disappear (like the Animating Deletion example)
Of course, the nodes would have to be in the group when the user clicks the expand button.
I have tried a few simple animations (translate, rotate, disappear) but didn’t see anything related to animating (or moving) nodes into or out of groups.