User textblock edit with cascading consequences

Hello,

after the user has edited a textblock in a given node, my application has to immediately propagate changes to the data of all descendent nodes. (No cycles allowed in the diagram, so this is a one-way flow without possible loops.)

What’s the correct event hook/textblock property to latch onto? Is there an example of this?

I looked through the changedEvents documentation, but I couldn’t figure out the proper way of doing this. The documentation furthermore says that the event listeners should not make further changes to the model data, but this is precisely what I need to do (preferably within the same transaction). Also, changing the textblock doesn’t seem to fire the listener I tried to add via addModelChangedListener or addChangedListener.

I also thought about using the textValidation function of the textblock, but it seems unclean to cause side-effects in this way – and seems to break the TextBlock editing, anyway.

Analogously to the click property of a node or the textValidate property of the textblock, is there an onEdit property for the textblock which allows me to directly add a listening function, given that a change has been successfully made, allowing me to make other changes in the diagram before the transaction is committed?

Many thanks
F

There’s a Diagram event for that. Either write:

myDiagram.addDiagramListener('TextEdited', function(e) {
  // do stuff
  // e.subject is the textblock so e.subject.part is the Node
});

Or:

myDiagram =
  $(go.Diagram, "myDiagramDiv", // must be the ID or reference to div
    {
      //  init stuff like:
      initialContentAlignment: go.Spot.Center,
      // TextEdited listener:
      "TextEdited": onTextEdited,
      // ... rest of diagram constructor



function onTextEdited(e) {
  // do stuff
}

This event is raised right before the TextEditingTool’s transaction is completed.

Thanks Simon, that’s an improvement. However it seems finally not to work for me: the graph doesn’t update, and I am stuck with a floating editing textbox that won’t disappear or interact. Go-debug.js outputs exactly the same error messages it does when first loading the model (mostly cannot modify GraphObject.name on Panel). This problem appears to be caused by calling model.setDataProperty during the TextEdited event, although after looking at it for a while I am not sure I get it yet.

I’ll continue digging – any pointers at this stage?

Cheers
F

Modifying the GraphObject.name of elements within a Node or a Link seems like a bad idea to me. As the error indicates – such behavior is not supported. Maybe you have a Binding on the GraphObject.name property of some element?

Hi Walter,

I understand it’s not supported, but it does seem to be working, and it’s very useful. It’s related to the click event we discussed in the other thread – I use a go.Binding("name","whatever") on an itemArray and then a node.findObject(whatever) to toggle the visible property of the element in question. It’s effectively a solution to parametrising the target of the panel expander buttons. If you can suggest a more elegant/framework-aligned way of doing it, that would be great, but for the problem in this thread it’s an aside.

Best
F

I just tried what Simon suggested, and it worked as I believe you would like it to work:

      $(go.Diagram, "myDiagramDiv",
        {
          "TextEdited": function(e) {
            var tb = e.subject;  // the edited TextBlock
            var oldstr = e.parameter;
            var newstr = tb.text;
            var subtree = tb.part.findTreeParts();  // the subtree, including the Node itself and all connecting Links
            subtree.each(function(p) {
              if (p instanceof go.Node && p !== tb.part) {
                p.diagram.model.setDataProperty(p.data, "text", p.data.text + ".");
              }
            })
          },
          . . .

It does indeed. I wasn’t careful enough with making copies of dictionaries, leading to some strange interaction with the model.setDataProperty not registering the changes. Doing a deep copy of the node data object before modifying it and setting the new data property made it work.

Many thanks Simon and Walter.

Hello,

at the point of the TextEdited event, I think the new data is not yet actually committed. If I call model.findNodeDataForKey(key), the node data returned is the un-edited data.

How can I access the newly-changed/in-the-process-of-being-changed data during this (or another) event? I see that the DiagramEvent.parameter is the old value, is the new value accessible somewhere?

If the new parameter value is available during the TextEdited event, I would be tempted to call model.setDataProperty(data,property,newvalues) at the beginning of my event handler, so that the new data is available for use during the rest of the handler. Let me know if this is a bad idea

Thanks
F

Could you confirm that both the “oldstr” and “newstr” variables are what you would expect?

So it is, thank you. Do I have to call a model.setDataProperty with the new value at this stage for the new data to be changed in the model, or is there an event I can hook into where the new values are already set (but before the transaction is committed)?

If there is a TwoWay Binding on the TextBlock.text property whose source is some property on the data, that data property should already have been set.

Thanks Walter, you’re right. I forgot that it hadn’t been set to TwoWay.