Some newbie questions

Hello,

Your component is just amazing.

I’m sorry for my looooong topic (and for my bad english) but I have some newbie questions :

If understand, each item in the nodeDataArray correspond to a node (a group or a non link part). We can use binding to link an attribute value to an object property (like the fill color).

[ 
 { key: "123", attribute1: 'A', attribute2: 'B' },
 { key: "234", attribute1: 'A', attribute2: 'B' }
]

When we use an itemArray to create children components, binding in the itemTemplate it refers to the child attribute (so only the attribute3).

[ 
 { key: "123", attribute1: 'A', attribute2: 'B' , children: [ { key: '1123', attribute3: 'C' ]},
 { key: "234", attribute1: 'A', attribute2: 'B' , children: [ { key: '1123', attribute3: 'C' ]}
]

Add properties dynamically

Imagine, each node child is a port and we want to add some properties dynamically (to simplify the initial model). How do add this properties from the itemTemplate or another place to the model (I know I can listen a changedEvent to add this properties but is it the correct way) ? My itemtemplate is like this…

itemTemplate() {
  const circle = this.go(go.Shape, 'Rectangle',
    {
      strokeWidth: 0,
      desiredSize: new go.Size(12, 12),
      cursor: 'pointer',
      fromSpot: go.Spot.Left,
      toSpot: go.Spot.Right,
    },
    new go.Binding('fromLinkable', 'fromLinkable'),
    new go.Binding('toLinkable', 'toLinkable'),
    new go.Binding('portId', 'portId'),
  );

  const panel = this.go(go.Panel, 'Horizontal', {
     alignment: go.Spot.Left,
     margin: new go.Margin(2, 2),
  });

  panel.add(circle);

  return panel;
}

I tried to add new data property like this :

model.setDataProperty(circle, 'acustomproperty', false);

But I receive a “GraphLinksModel.setDataProperty is modifying a GraphObject, “Shape(Rectangle)#488” Is that really your intent?” message and the corresponding parts in the node.data are not updated. So at this time, is use a binding to add this values, but it’s probably not the correct way to do it :

this.go(go.Panel, 'Vertical',
  this.addProperties(),
  {
     itemTemplate: this.itemTemplate(),
   },
),

...

addProperties() {
  const bind = new go.Binding('itemArray', 'ports');
  bind.converter = (ports, target) => {
    const value = ports.map((port) => {
      port.acustomproperty = null;
      return port;
    });
    if (value === undefined) return target.itemArray;
    return value;
  };
  return bind;
}

#2 Update child property from events

Now imagine a link is created (or relinked, or deleted) between two nodes port. I listen the LinkDrawn, LinkRelinked or SelectionDeleted events. I can retrieve the from/to Node and from/to Port but how to update the corresponding “acustomproperty” of each port in the model for the selected node. Once time again I tried with :

model.setDataProperty(e.subject.fromPort, 'acustomproperty', true);

I have the same message "GraphLinksModel.setDataProperty is modifying a GraphObject, “Shape(Rectangle)#488”.

At this time (and it’s a workaround), I change (the code is more complex) the data property like this :

onLinked(e) {
  const fromNode = e.subject.fromNode;
  const index = fromNode.data.ports.findIndex((port) => {
    return port.portId === portId;
  });

  fromNode.data.ports[index].acustomproperty = true;
  ...

#3 Colored link

On the onLinked method above, I “compute” the color link (and other properties) from properties retrieves on each port. At this time (and it’s allways a workaround), I get this value like this :

onLinked(e) {
   ...

  const ret = toNode.data.ports.filter((port) => {
     return port.portId === portId;
  });

  let toAnotherproperty = null;
  if (ret.length !== 0) {
     toAnotherproperty = ret[0].anotherproperty;
  }

  ...
  if (fromAnotherProperty === 1 && toAnotherProperty === 1) linkColor = '#FF0000';
  ...

Two questions in one :

1. How to get this value (the are no getDataProperty)
2. That work’s perfectly for a new link but not for links created from the linkDataArray. In this case, how to modify properties of each links created by the linkDataArray before it draw them ? I can add a listener on addModelChangedListener and modify each link when the transaction is finished but is this the correct method ?

#2 Mapping

It’s my last question :) How to create a mapping to retrieve from a child a parent attribute ?

Thanks you !

This seems like a lot of Q’s. First I suggest reading this tutorial on manipulating graph objects which goes over setDataProperty.

model.setDataProperty(panel.data, 'acustomproperty', false); or something ought to be correct. setDataProperty must be done with the data object.

Yes, a binding is probably not appropriate just to add properties programmatically.

  1. How to get this value (the are no getDataProperty)

panel.data contains all the data for each item in an itemArray. Node.data is similar.

It’s my last question :) How to create a mapping to retrieve from a child a parent attribute ?

In a binding, or elsewhere? You can also look at panel.part.data to get the Node’s data, if you have a reference to the item.


If you want to tell me more broadly what you’re doing, perhaps I can give more clear advice here.