memberAdded & online info

Hi,

I have a question on this event, here’s the story:
I need to check with a recursive function the creation of some ports on the parent group of the node added. For example : I drag two group nodes, one with key “foo” and group property “foo” (default) and the second group with key “goo” and group “goo”. When they are both on canvas I drag “goo” into “foo”. The result now is that I have group “goo” with key “-1” and group property=“foo”, “foo” group node remains the same. This is the normal behaviour at the end of the action, but when I check it in the memberAdded event after the drag, the dragged group still have group property equal to key property, why? I need to know exactly what node’s been dragged and what is its parent because I need to check recursively on parents going up on the tree… I need to specify something else on the function or this is a normal behaviour? If it’s so are there some others action that I can do to obtain the parent of the dragged object after the dragging?
Pls help
Thx

Are you saying that you have a model whose Model.nodeDataArray consists of something like:

[
  { key: "foo", isGroup: true, group: "foo" },
  { key: "goo", isGroup: true, group: "goo" }
]

That’s not a valid graph, because no group can be a member of itself.

The DraggingTool does not change the group membership of any nodes. That is only done by implementing an event handler that makes such changes, whether in the diagram by setting Part.containingGroup or in the model by setting data.group. The Group.addMembers method is a convenient way to do that, or the CommandHandler.addTopLevelParts method for removing parts from any groups that they were member of.

Those actions will in turn cause Group.memberAdded or Group.memberRemoved event handlers to be called.

For a demonstration I added this event handler to the Group template of the Regrouping sample, https://gojs.net/latest/samples/regrouping.html:

            memberAdded: function(group, part) {
              console.log("Added", part.key, "to", group.key)
            },

Then when I drag a node from one group and drop into another group, the console message correctly identifies the dragged node and its new containing group.

Here’s a more complete modification of the Regrouping sample.

Add these event handlers to the group template:

            memberAdded: function(group, part) {
              console.log("Added", part.data.text, "to", group.data.text)
            },
            memberRemoved: function(group, part) {
              console.log("Removed", part.data.text, "from", group.data.text)
            },
            containingGroupChanged: function(part, oldgroup, newgroup) {
              console.log("changed membership", part.data.text,
                          "from", oldgroup ? oldgroup.data.text : "top-level",
                          "to", newgroup ? newgroup.data.text : "top-level");
            },

Add this to the node template:

            containingGroupChanged: function(part, oldgroup, newgroup) {
              console.log("changed membership", part.data.text,
                          "from", oldgroup ? oldgroup.data.text : "top-level",
                          "to", newgroup ? newgroup.data.text : "top-level");
            },

And now, both during initialization and as the user drag-and-drops, you can see all of the messages going by, describing the changes that have happened.

Probably my mistake depends on the fact that I need to handle both drag&drop from html and drag&drop from viewport because when I add a group I also set the group property with the same key… As you rightly said this is not correct but helps me to find a way out when I process a recursive function, because if I find that group is equal to key/text means that group is the highest and the principal father of the underlying children. So this behaviour depends on my error of defining group property as the same of the key. But if I don’t define the group property in the addNode function, group is written automatically? Or it’s written only when the node/group is added to a group? and by the way…is there an easy way to detect the highest containing group in a diagram? (the condition is that the diagram can only contain one main group containing other groups or node)

When you set Part.containingGroup, it will update the model data for that Part.
When you set data.group, it will update the Part and the Group in the Diagram.

Diagram.findTopLevelGroups()

Ooops… I did a try but the behaviour remains the same… I pulled out the group property from both the groups dragged, one with key -1 (no group) and the second with key -2 (no group). In the addedMember I checked the dragged node:

    		  memberAdded: function(grp,prt){ 
    			  			processParentGroupRec(prt);

where in the processParentGroup I check the prt object like that:

		function processParentGroupRec(node){
			if(node == undefined) return;
			if(node.data.group!=undefined &&
                        ....

the node.data.group is “undefined” but it must be populated with the key of the parent, isn’t it?
What’s wrong in my code?

taking a look at the textbox I see:

{"isGroup":true, "text":"Prodotto", "loc":"881 -187.89999999999998", "horiz":"#33D3E5", "rightArray":[ {"portId":"Ambito", "checked":true},{"portId":"Scalo", "checked":true} ], "source":"/FILL_EM/img/mult.png", "key":-2, "group":-1}

and group, at the end of all actions is rightly populated with -1…

Just to understand if it was my fault I did exactly what you said, modifying the regrouping example with your code and as I’ve just seen before, in addedMember function the group property in the added node group is still not present until the model is completely reloaded…I guess it’s a matter of timing

I see what you mean. If I use this event handler on the Group template:

            memberAdded: function(group, part) {
              console.log("Added", part.key, part.data.text, part.data.group, "to", group.key, group.data.text)
            },

and this handler on the Node template:

            containingGroupChanged: function(node, oldgrp, newgrp) {
              console.log("Changed", node.key, node.data.text, node.data.group, "to", newgrp.key, newgrp.data.text)
            },

when I drag the simple node “second C” into a different group “Main 1”, I get these messages:

Added -13 second C 5 to 1 Main 1
Changed -13 second C 1 to 1 Main 1

So in the Group.addedMember event handler, the node data’s data.group property hasn’t been updated yet, but by the time the Part.containingGroupChanged event handler is called, it has been updated.

I guess that’s the problem with providing notices on both the node changing membership as well as the group changing members and having references in both directions.

Nevertheless, the arguments passed to both event handlers is still correct, in my opinion.

But the event Part.containingGroupChanged is fired if you move an element from a group to another one, not if you simply drag a groupless element into another…or not?
My problem is that I need to have the containing group key when I drag anything into a group. If there’s a delay I have a big problem… My goal is to use a single recursive function that scan the whole tree of parent from a dragged node, and I must start all at the end of drag…I can’t handle an asyncronous event…

Solved. Part.containingGroupChanged is fired anyway, and that has the group property set. Good news.
Thx