Go diagram port link not coming from selected port

Hi,
I am trying to create a diagram with multiple port,
1.while I try to connect one node to another node by a link it is taken as center of any direction based on TO node location.
2.I want to create a link like Data Flow Diagram as one to one link from port to To port.
I unable to achieve this by gojs. I have attached My template here:

diagram template:
$(go.Node, ‘Spot’,
{ name: ‘TOP_PANEL’, fromLinkable: true,
toLinkable: true,
toMaxLinks: 3,
fromMaxLinks: 1,
fromSpot: go.Spot.Top,
toSpot: go.Spot.Bottom,
doubleClick: (e, obj) => { this.nodeClicked(e, obj); } },
{ locationSpot: go.Spot.Center },
new go.Binding(‘location’, ‘loc’, go.Point.parse).makeTwoWay(go.Point.stringify),
{ selectable: true, selectionAdornmentTemplate: this.nodeSelectionAdornmentTemplate() },
// { resizable: true, resizeObjectName: ‘PANEL’, resizeAdornmentTemplate:
this.nodeResizeAdornmentTemplate() },
// { rotatable: true, rotateAdornmentTemplate: this.nodeRotateAdornmentTemplate() },
new go.Binding(‘angle’).makeTwoWay(),
// the main object is a Panel that surrounds a TextBlock with a Shape
$(go.Panel, ‘Auto’,
{ name: ‘PANEL’ },
new go.Binding(‘desiredSize’, ‘size’, go.Size.parse).makeTwoWay(go.Size.stringify),
$(go.Shape, // default figure
{
portId: ‘’, // the default port: if no spot on link data, use closest side
fromLinkable: true, /toLinkable: true,/ cursor: ‘pointer’,
fill: ‘white’, // default color
strokeWidth: 2,
name:‘TITLE_SHAPE’
},
new go.Binding(‘figure’).makeTwoWay(go.Point.stringify),
new go.Binding(‘fill’).makeTwoWay(go.Point.stringify)),
new go.Binding(‘width’).makeTwoWay(go.Point.stringify),
$(go.Panel, ‘Table’,
{ defaultRowSeparatorStroke: null, name:‘TITLE_TABLE’ },
// header
$(go.Picture,
{
row: 0, columnSpan: 1, alignment: go.Spot.Left,
margin: 10, width: 20, height: 20, background: ‘white’
},
new go.Binding(‘source’, ‘img’).makeTwoWay(go.Point.stringify)),
$(go.TextBlock,
{
row: 0, columnSpan: 2, margin: 0, width: 100, alignment: go.Spot.Center,
font: ‘bold 12pt sans-serif’,
isMultiline: true, editable: true
},
new go.Binding(‘text’, ‘text’).makeTwoWay(go.Point.stringify),
),

                                $(go.TextBlock,
                                    {
                                        row: 1, columnSpan: 2, margin: 1, width: 100, alignment: go.Spot.Center,
                                        font: '8pt sans-serif',
                                        //   isMultiline: true, editable: true
                                    },
                                    new go.Binding('text', 'typeText').makeTwoWay(go.Point.stringify),
                                ),
                                $(go.Panel, 'Table',
                                { defaultRowSeparatorStroke: 'gray', name:'DESCRIPTION_TABLE', row: 2, columnSpan: 
                              2, width:200 },
                                $(go.TextBlock,
                                    {   stroke: 'gray',
                                        row: 1, columnSpan: 2, margin: 1, alignment: go.Spot.Center,
                                        font: 'bold 8pt sans-serif',
                                        width:200,
                                        height:30
                                        // defaultRowSeparatorStroke: 'gray'
                                        //   isMultiline: true, editable: true
                                    },
                                    new go.Binding('text', 'description').makeTwoWay(go.Point.stringify),
                                ),
                                new go.Binding('width', 'width').makeTwoWay(go.Point.stringify)
                                ),
                                new go.Binding('width', 'width').makeTwoWay(go.Point.stringify)
                            )
                        ),
                        $(go.Panel, 'Horizontal',
                        {
                        alignment: go.Spot.Top,
                        alignmentFocus: new go.Spot(0.5, 0, 0, -8)
                        },
                        [this.makePort('IN', true)]),
                        $(go.Panel, 'Horizontal',
                        {
                        alignment: go.Spot.Bottom,
                        alignmentFocus: new go.Spot(0.5, 1, 0, 8),
                        name:'OUT'
                        },
                        [this.makePort('OUT', false)]),
                        $(go.Panel, 'Horizontal',
                                { defaultRowSeparatorStroke: null,
                                name: 'BOTTOM_PANNEL',
                                alignment: go.Spot.Bottom,
                                toLinkable: true,
                                alignmentFocus: new go.Spot(0.5, 1, 0, 8)
                                }),
                 
                        
                        { 
                            mouseEnter: (e, node) => { this.showSmallPorts(node, true); }
                            // mouseLeave:  (e, node) => { this.showSmallPorts(node, false); }
                        }
                    );

Palette Template:

        $(go.Node, 'Horizontal',
        {
            // click: this.nodeClicked,
            // doubleClick: this.nodeClicked,
            // background: '#44CCFF',
            // background:'#3faeec',
            background: 'white',
            contextMenu:
                $(go.Adornment, 'Vertical',
                    $('ContextMenuButton',
                        $(go.TextBlock, 'Properties'),
                        // { click: showProperties }
                    )
                )
        },
        /*$(go.Shape, 'Rectangle',
            { fill: 'lightgray' },
            { portId: '', fromLinkable: true, toLinkable: true, cursor: 'pointer' }),*/
        $(go.Picture,
            // { maxSize: new go.Size(16, 16) },
            { margin: 10, width: 30, height: 30, background: 'white' },
            new go.Binding('source', 'img')),
        $(go.TextBlock,
            { margin: 12, stroke: 'black', font: 'bold 16px sans-serif', width: 200 },
            new go.Binding('text', 'key'),
            new go.Binding('key', 'key'),
            ),
        new go.Binding('figure')
        // $(go.TextBlock,
        //     { margin: 3 },
        //     new go.Binding('text', 'key'))
    );

Link Template:
$(go.Link, // the whole link panel
{ selectable: true, selectionAdornmentTemplate: this.linkSelectionAdornmentTemplate() },
{ relinkableFrom: true, relinkableTo: true, reshapable: true },
{
routing: go.Link.AvoidsNodes,
curve: go.Link.JumpOver,
corner: 5,
toShortLength: 4
},
new go.Binding(‘points’).makeTwoWay(),
$(go.Shape, // the link path shape
{ isPanelMain: true, strokeWidth: 2 }),
$(go.Shape, // the arrowhead
{ toArrow: ‘Standard’, stroke: null }),
$(go.Panel, ‘Auto’,
new go.Binding(‘visible’, ‘isSelected’).ofObject(),
$(go.Shape, ‘RoundedRectangle’, // the link shape
{ fill: ‘#F8F8F8’, stroke: null }),
new go.Binding(‘figure’),
$(go.TextBlock,
{
textAlign: ‘center’,
font: ‘10pt helvetica, arial, sans-serif’,
stroke: ‘#919191’,
margin: 2,
minSize: new go.Size(10, NaN),
editable: true
},
new go.Binding(‘text’).makeTwoWay())
)
);

Port generation code:
this.currentSelectedNode = this.diagram.findNodeForData(this.getNodeByKey(key));
if (this.currentSelectedNode.data && this.currentSelectedNode.data.key.indexOf(‘Switch’) == -1) {
return;
}
this.diagram.startTransaction(‘start update’+key);
this.diagram.model.setDataProperty(this.currentSelectedNode.data, ‘initLog’, ‘true’);
pinCount = this.currentSelectedNode.data.pinCount || pinCount;
let out = this.currentSelectedNode.findObject(‘OUT’);
if (out) {
this.currentSelectedNode.remove(out);
}
for (let i = 1; i <= pinCount; i++) {
let port = $(go.Shape, ‘Circle’,
{
row: 0, columnSpan: i,
fill: ‘gray’,
// fill: null,
stroke: null,
desiredSize: new go.Size(8, 8),
portId: ‘p’ + i, // declare this object to be a ‘port’
toMaxLinks: 1, // don’t allow more than one link into a port
cursor: ‘pointer’ // show a different cursor to indicate potential link point
});
var panel = $(go.Panel, ‘Vertical’,
{ margin: new go.Margin(0, 2) }
);
var lab = $(go.TextBlock, ‘p’ + i, // the name of the port
{ font: ‘7pt sans-serif’ });
port.fromSpot = go.Spot.Bottom;
port.fromLinkable = true;
lab.margin = new go.Margin(1, 1, 0, 0);
panel.alignment = go.Spot.BottomCenter;
panel.add(lab);
panel.add(port);
// ports.push(panel);
// table.add(panel);
this.currentSelectedNode.findObject(‘BOTTOM_PANNEL’).add(panel);
}
// this.currentSelectedNode.findObject(‘BOTTOM_PANNEL’).add(table);
// this.currentSelectedNode.part.diagram.nodeTemplate
// .setCategoryForNodeData(obj.part.diagram.nodeTemplate, this.templateKey);
this.diagram.commitTransaction(‘start update’+key);

Kindly help me where I did mistake

Ummm, could you please be more specific about what the problem is?

Thank @walter, I have multiple port in a node while I create link it is not staying with that selected port. Link always moving to the center of node. Please refer Bellow images
ours: https://photos.app.goo.gl/KL3LSwkrVGShwqQUA
expected : https://photos.app.goo.gl/EpnFzhCKZaoo33oJ7

https://gojs.net/latest/intro/ports.html#GeneralPorts

Hi Walter, I found what is the issue and fixed. below code I have missed out.
this.diagram.model.linkFromPortIdProperty = “fromPort”; // necessary to remember portIds
this.diagram.model.linkToPortIdProperty = “toPort”;