Resizing custom SVG nodes

Is there anyway to save the sizes of a node if it is given a custom geoString for how it’s displayed?

When I’m pulling out the model from the diagram to be saved to the database, I’m seeing the following values within when I console.log() them:

<div ="console-message-wrapper="" console-adjacent-user-command-result"="" style="-sizing: border-; border-bottom-style: none; display: flex; color: rgb48, 57, 66; font-family: 'dejavu sans mono', monospace; font-size: 11.111111640930176px; line-height: normal; : rgb255, 255, 255;"><div ="console-user-command"="" style="-sizing: border-; clear: right; : relative; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb240, 240, 240; padding: 1px 22px 1px 0px; margin-left: 24px; min-height: 16px;"><span ="console-message-text="" source-code"="" style="-sizing: border-; white-space: pre-wrap; color: rgb0, 128, 255; font-size: 11px !imant;">console.log(oNode.height);</span><div ="console-message-wrapper"="" style="-sizing: border-; display: flex; color: rgb48, 57, 66; font-family: 'dejavu sans mono', monospace; font-size: 11.111111640930176px; line-height: normal; : rgb255, 255, 255;"><div ="console-message="" console-log-level="" console-user-command-result"="" style="-sizing: border-; clear: right; : relative; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb240, 240, 240; padding: 1px 22px 1px 0px; margin-left: 24px; min-height: 16px; flex: 1 1 auto;"><span ="console-message-text="" source-code"="" style="-sizing: border-; white-space: pre-wrap; font-size: 11px !imant;"><span style="-sizing: border-;"><span ="console-atted-="" source-code"="" style="-sizing: border-; : relative; display: inline-block; vertical-align: top; color: inherit; font-size: 11px !imant;"><span ="console--preview"="" style="-sizing: border-; font-style: italic;">Object {<span ="name"="" style="-sizing: border-; color: rgb136, 19, 145;">class</span>: <span ="console-atted-"="" style="-sizing: border-; color: rgb196, 26, 22; white-space: pre; unicode-bidi: -webkit-isolate;">"NaN"</span>}</span></span></span></span>
<div ="console-message-wrapper="" console-adjacent-user-command-result"="" style="-sizing: border-; border-bottom-style: none; display: flex; color: rgb48, 57, 66; font-family: 'dejavu sans mono', monospace; font-size: 11.111111640930176px; line-height: normal; : rgb255, 255, 255;"><div ="console-user-command"="" style="-sizing: border-; clear: right; : relative; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb240, 240, 240; padding: 1px 22px 1px 0px; margin-left: 24px; min-height: 16px;"><span ="console-message-text="" source-code"="" style="-sizing: border-; white-space: pre-wrap; color: rgb0, 128, 255; font-size: 11px !imant;">console.log(oNode.width);</span><div ="console-message-wrapper"="" style="-sizing: border-; display: flex; color: rgb48, 57, 66; font-family: 'dejavu sans mono', monospace; font-size: 11.111111640930176px; line-height: normal; : rgb255, 255, 255;"><div ="console-message="" console-log-level="" console-user-command-result"="" style="-sizing: border-; clear: right; : relative; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb240, 240, 240; padding: 1px 22px 1px 0px; margin-left: 24px; min-height: 16px; flex: 1 1 auto;"><span ="console-message-text="" source-code"="" style="-sizing: border-; white-space: pre-wrap; font-size: 11px !imant;"><span style="-sizing: border-;"><span ="console-atted-="" source-code"="" style="-sizing: border-; : relative; display: inline-block; vertical-align: top; color: inherit; font-size: 11px !imant;"><span ="console--preview"="" style="-sizing: border-; font-style: italic;">Object {<span ="name"="" style="-sizing: border-; color: rgb136, 19, 145;">class</span>: <span ="console-atted-"="" style="-sizing: border-; color: rgb196, 26, 22; white-space: pre; unicode-bidi: -webkit-isolate;">"NaN"</span>}</span></span></span></span>

Is this purely an issue with using custom SVG strings or is there a way around this?

Thanks in advance.

The values for GraphObject.width and .height are identical to the respective values of GraphObject.desiredSize, which defaults to NaN x NaN.

If you set or data bind Shape.geometryString and get the right results the first time (in terms of Shape actualBounds and Node.actualBounds), why aren’t you getting exactly the same results when you load them again? Basically I’m wondering why you believe you need to save the size in the model.

But the general answer to your question is to establish a TwoWay Binding on the property that you want to save if the value changes. Note that the value will not be saved unless the value is altered after initialization. So setting a TwoWay bound property to some value in the template will not cause the value to be copied to the model, until some code changes the value while the Part is in the Diagram.

The node can be resized by the user, in terms of creating the nodes first time round they maintain the correct and consistent size. However if they wish to change the size of a node then it does not stay persistent due to reading it as NaN, and so when they next load in the diagram it appears as the default size.

I have both a ‘width’ and ‘height’ two-way binding within my nodeTemplate, however wherever I put it the the SVG size does not change… I only get the object I put in my first post as part of the node data once I change the size of a node, otherwise I get no height or width property (as expected).

Originally I had my nodeTemplate set like this:


            oDiagram.nodeTemplate = goJs(go.Node, go.Panel.Vertical, {
                layoutConditions: go.Part.LayoutStandard & ~go.Part.LayoutNodeSized, 
                locationSpot: go.Spot.Center,
                locationObjectName: 'shape',
                resizable: true,
                resizeObjectName: 'shape', // user can resize the Shape
                selectionAdorned: false, // no selection handle when selected
                contextMenu: goJs(go.Adornment)
                },
                new go.Binding('location', 'loc', go.Point.parse),
                // new go.Binding('width', 'width'),
                // new go.Binding('height', 'height'),
                // define the node's outer shape, which will surround the TextBlock
                goJs(go.Shape, {
                    name: 'shape',
                    strokeWidth: 2
                },
                new go.Binding('fill', 'colour'),
                new go.Binding('geometryString', 'geoString'),
                new go.Binding('stroke', 'stroke'),
                new go.Binding('width').makeTwoWay(),
                new go.Binding('height').makeTwoWay()), 
                goJs(go.TextBlock, {
                    font: 'bold 10pt helvetica, bold arial, sans-serif',
                    margin: 4
                },
                new go.Binding('text', 'text'))
            );

This allowed me to change the size of the actual SVG itself but not be able to save it, I have tried putting it inside something else and allowing that to resize since:


            oDiagram.nodeTemplate = goJs(go.Node, 'Auto',
                {
                    layoutConditions: go.Part.LayoutStandard & ~go.Part.LayoutNodeSized, 
                    locationSpot: go.Spot.Center,
                    resizable: true,
                    name: 'shape',
                    locationObjectName: 'shape',
                    resizeObjectName: 'shape', // user can resize the Shape
                    selectionAdorned: true, // no selection handle when selected
                    contextMenu: goJs(go.Adornment),
                },
                goJs(go.Panel, 'Vertical',
                    goJs(go.Shape,
                        {
                            strokeWidth: 2
                        },
                        new go.Binding('fill', 'colour'),
                        new go.Binding('geometryString', 'geoString'),
                        new go.Binding('stroke', 'stroke')
                    ),
                    goJs(go.TextBlock,
                        {
                            font: 'bold 10pt helvetica, bold arial, sans-serif',
                            margin: 4
                        },
                        new go.Binding('text', 'text')
                    ),
                    new go.Binding('location', 'loc', go.Point.parse)
                ),
                new go.Binding('width').makeTwoWay(),
                new go.Binding('height').makeTwoWay()
            );

However this allows me to resize a box around the SVG and text. All that happens is that the text will either take up more/less lines depending on how I change the size of the node, the SVG remains a consistent size, but the size of the panel they are in is saved properly (although it has almost no bearing on the diagram overall) .

I have tried moving the ‘name: “shape”’,‘new go.Binding(“width”).makeTwoWay()’ and ‘new go.Binding(“height”).makeTwoWay()’ attributes/properties around the node to affect which part of it is resizeable, however this doesn’t usually help me in any way.

The first template looks OK to me, because you specified the Part.resizeObjectName to be the name of the Shape, and because the TwoWay Binding of width and height are on that Shape. It is not clear to me why that is not working.

One thing you could try: replace both Bindings with a single TwoWay Binding of “desiredSize”.

What version are you using?

I’ve tried changing to a ‘desiredSize’ binding on both example node templates, it now correctly extracts data as an object containing valid data, however when loading this data into the diagram it ignores the sizing and draws them as their original size.

I am currently using version 1.4.14

If you used Model.toJson and .fromJson, that should have worked.

Did you use a Binding such as:
new go.Binding(“desiredSize”, “size”, go.Size.parse).makeTwoWay(go.Size.stringify)

Yes, that is the way I used the binding…

Using .toJson and .fromJson in the following manner;


            var
            jsonModel;

            jsonModel = this.diagram.model.toJson();

            this.diagram.model = window.go.Model.fromJson(jsonModel);

gives me the following error in goJS:

'Uncaught TypeError: Cannot read property ‘x’ of undefined

Do you have a stack trace?

Does the JSON text have the right information in it?
Can you show the smallest failing example?

Never mind, I found the issue was something to do with my code elsewhere reacting to it for some reason…

Using .toJson and .fromJson seems to allow the nodes to be re-rendered at the correct size, which is interesting. I don’t store the exact contents of .toJson() in the database due to custom geoStrings being quite long and them being stored elsewhere anyway, however I do take out the desiredSize attribute and store that, so I’m unsure as to why reloading a diagram from the database doesn’t allow it to be automatically set to the desired size

Fixed this using the ‘desiredSize’ binding…

Unlike when binding ‘points’, ‘height’ or ‘width’ the ‘desireSize’ binding is applied to a ‘size’ attribute on the node and I didn’t notice this, so I was trying to retrieve it from a node attribute of ‘desiredSize’…

Changed it to take the value from ‘size’ and all is working fine now, thanks.