Issues applying location to diagram

Hello!

I am currently applying a location to a new node and I’ve tested and logged the locations and it is getting and saved to the diagram in location/loc but on the diagram it self, the node is not at the location set.

For testing purposes I set static locations with:

>           diagram.model.addNodeData({
>             location: new go.Point(100,0),
>             text: event.dataTransfer.getData('text'),
>           })

I’ve tried different points such as (0,100),(0,0),(50,50) and they all set the node on the bottom right of the diagram.

My diagram is defined as below:

> const myDiagram = $(go.Diagram, this.$el, {
>       layout: $(go.TreeLayout, {
>         angle: 0,
>         arrangement: go.TreeLayout.StyleLayered
>       }),
>       'undoManager.isEnabled': true,
>       'linkingTool.isUnconnectedLinkValid': true,
>       'linkingTool.portGravity': 20,
>       'relinkingTool.isUnconnectedLinkValid': true,
>       'relinkingTool.portGravity': 20,
>       'relinkingTool.fromHandleArchetype': $(go.Shape, 'Diamond', {
>         segmentIndex: 0,
>         cursor: 'pointer',
>         desiredSize: new go.Size(8, 8),
>         fill: 'tomato',
>         stroke: 'darkred'
>       }),
>       'relinkingTool.toHandleArchetype': $(go.Shape, 'Diamond', {
>         segmentIndex: -1,
>         cursor: 'pointer',
>         desiredSize: new go.Size(8, 8),
>         fill: 'darkred',
>         stroke: 'tomato'
>       }),
>       'linkReshapingTool.handleArchetype': $(go.Shape, 'Diamond', {
>         desiredSize: new go.Size(7, 7),
>         fill: 'lightblue',
>         stroke: 'deepskyblue'
>       }),
>       // Model ChangedEvents get passed up to component users
>       ModelChanged(e) {
>         self.$emit('model-changed', e)
>       },
>       ChangedSelection(e) {
>         self.$emit('changed-selection', e)
>       }
>     })
>
> window.devicePixelRatio = myDiagram.computePixelRatio()

And the template I am currently just using the exact template from the Drag and Drop example:

>    myDiagram.nodeTemplate =
>         $(go.Node, "Auto",
>           { locationSpot: go.Spot.Center },
>           new go.Binding('location'),
>           $(go.Shape, "Rectangle",
>             { fill: 'white' },
>             // Shape.fill is bound to Node.data.color
>             new go.Binding("fill", "color"),
>             // this binding changes the Shape.fill when Node.isHighlighted changes value
>             new go.Binding("fill", "isHighlighted", function(h, shape) {
>               if (h) return "red";
>               var c = shape.part.data.color;
>               return c ? c : "white";
>             }).ofObject()),  // binding source is Node.isHighlighted
>           $(go.TextBlock,
>             { margin: 3, font: "bold 16px sans-serif", width: 140, textAlign: 'center' },
>             // TextBlock.text is bound to Node.data.key
>             new go.Binding("text"))
>         );

I have checked that the points passed were valid, I have also tried doing a two way bind for location and loc using

new go.Binding(‘location’, ‘loc’, go.Point.parse).makeTwoWay(go.Point.stringify)

replacing new go.Binding(‘location’)

I have also read that layouts prevent setting exact locations on a post and tried removing the layout but no luck. Is there something else I am missing to enable locations or something I am doing wrong?

I suspect that what is happening is that you have set a Diagram.layout and you are setting the Node.location via a data Binding. So you have two different ways to assign the locations of nodes, and that is a conflict. As it so happens, when each Node is created and its Bindings are evaluated, the Node will get the expected location from the model data. But then the diagram’s layout is performed, which moves all of the nodes according to whatever algorithm the layout has.

Usually if you expect to load nodes with locations specified in the model, you want to disable the layout so that it does not run. So I suggest that you at least set Layout.isInitial to false on your TreeLayout. You might want to add more control over when the layout runs.

Read more about the possibilities at https://gojs.net/latest/intro/layouts.html#LayoutInvalidation.

I tried setting isInitial to false as well as isOngoing but no luck. I also tried just removing the layout completely and it still has the same outcome.

What is the outcome?

If a Node is not where you expect it to be, check in the debugger the value of its Node.location.

If it is what you would expect, then maybe you are not talking about its location or position, but about the Diagram’s Diagram.position because the viewport has been scrolled. https://gojs.net/latest/intro/viewport.html

If it is not what you would expect and you have not set Diagram.layout at all, then I cannot explain why your Binding of the Node “location” property is not setting its location given by your Model.nodeDataArray’s corresponding node data object.

Sorry for the delayed reply,

It is not what I would expect.
The Node location is set to x: 204.784, y: 153, s: true
but what is being passed is x: 160.120, y: 88.654, s: false

So some how, the location is not being applied to the diagram or its being replaced with new ones.

Could you please show us your Node template’s property settings and bindings? And the model data for a minimal diagram exhibiting the problem, say with two nodes? Two small screenshots would be helpful, if you can show both what you are getting now and what you want instead.

My node template settings and bindings are posted above. I did also comment out the layout portion completely.

Here is the model data code when added.

    div.addEventListener(
        'drop', function(event) {
          // prevent default action
          // (open as link for some elements in some browsers)
          event.preventDefault()
          // Dragging onto a Diagram
          if (this === diagram.div) {
            const can = event.target
            const pixelratio = window.devicePixelRatio
            console.log(`pixel ratio: ${pixelratio}`)
            // if the target is not the canvas, we may have trouble, so just quit:
            if (!(can instanceof HTMLCanvasElement)) return
            const bbox = can.getBoundingClientRect()
            let bbw = bbox.width
            if (bbw === 0) bbw = 0.001
            let bbh = bbox.height
            if (bbh === 0) bbh = 0.001
            const mx =
              event.clientX -
              bbox.left * (can.width / pixelratio / bbw) -
              dragged.offsetX
            const my =
              event.clientY -
              bbox.top * (can.height / pixelratio / bbh) -
              dragged.offsetY
            console.log(mx, my)
            // const point = diagram.transformViewToDoc(new go.Point(mx, my))
            const point = new go.Point(mx, my)
            // const point = diagram.transformViewToDoc(new go.Point(100, 0))
            console.log(point)
            // add dropped block to our global dBlocks
            const id = event.dataTransfer.getData('id')
            const cl = event.dataTransfer.getData('class')
            vm.addDiagramBlock(id, cl)
            const blockLength = vm.$store.getters.dBlocks.length
            diagram.startTransaction('new node')
            diagram.model.addNodeData({
              location: point,
              text: event.dataTransfer.getData('text'),
              color: white,
              name: blockLength - 1
            })
            diagram.commitTransaction('new node')
          }

The base code I based off of everything off of and the outcome I would like is this following example:
https://gojs.net/latest/samples/htmlDragDrop.html

Where when you drop something from the left panel it drops exactly where the mouse is not in the center of the graph.

Please also note this is done in Vue, and happy late holidays! :)

I still don’t see what’s wrong. But it’s hard to read your unformatted code.

If the HTML Drag Drop sample works the way that you want your app to work, what differences are there between the sample and your app?

There are a few differences between the sample and my code.

First, the biggest, is in the sample the drop is where ever your cursor is and you let go of the mouse. On mine, when dropped, it is in center of the entire diagram.

Second, my code is set up in Vue, specifically using NuxtJS, following this example where there is are two components : https://gojs.net/latest/samples/vue.html?gclid=CjwKCAiA9JbwBRAAEiwAnWa4QzPF8cJgpif5NjICSdrPh6oV4ocKlunfm9wDiRqAmGzQMoDn1NojnRoCC5wQAvD_BwE

I just tried using just the exact code from the Drag and Drop example. I tried it where everything was in the Mounted() method and it worked just fine. I am guessing I am somehow not passing the location correctly between the two components? Which I find odd since I am able to pass different names of the nodes, color, and etc. Is there something special for location points?

Here is my diagram.vue formatted:
https://pastebin.com/3XHs2B8Y

and here is my goDiagram.vue formatted:
https://pastebin.com/VFvDKVhc

Does the problem also occur on the second and following drag-and-drops from different points in the source element to different points in the target diagram? Without screenshots it’s hard to visualuze what is happening.

It applies to all subsequent drag and drops. It seems like a layout is still being applied even though I have it commented out.

The next block would be added directly below it.

If you have left your Diagram.layout as an instance of TreeLayout, that would explain the behavior. But you say you have removed that assignment when you initialize your Diagram, yes? Leaving the Diagram.layout unassigned? You might want to check in the debugger whether myDiagram.layout.constructor === go.Layout.

And there are no Groups involved?