Port adjust dynamicaly according to link data property available

This requires a bunch of changes to your code that I have commented with “//** …”, and it requires a modification of SwimLaneLayout.

Here’s your modified code as a stand-alone sample:

<!DOCTYPE html>
<html lang="en">

<body>
    <script src="https://unpkg.com/[email protected]"></script>

    <div id="allSampleContent" class="p-4 w-full">

        <!-- SwimLaneLayout.js has been copied from extensions/ and been modified -->
        <script src="./SwimLaneLayout.js"></script>
        <script id="code">
            var DIRECTION = 0; // used to customize the layout and the templates, only upon first initialization

            function init() {
                if (window.goSamples) goSamples(); // init for these samples -- you don't need to call this

                var $ = go.GraphObject.make; // for conciseness in defining templates

                myDiagram = new go.Diagram('myDiagramDiv', {
                    // automatically scale the diagram to fit the viewport's size
                    initialAutoScale: go.AutoScale.Uniform,
                    // disable user copying of parts
                    allowCopy: false,
                    initialContentAlignment: go.Spot.LeftCenter,
                    // position all of the nodes and route all of the links
                    layout: $(SwimLaneLayout, {
                        laneProperty: 'group', // needs to know how to assign vertexes/nodes into lanes/groups
                        direction: DIRECTION, // Group template also depends on DIRECTION
                        setsPortSpots: false,
                        layerSpacing: 30,  //** should be bigger than the default value of 25
                        // layeringOption: go.LayeredDigraphLayout.LayerOptimalLinkLength,
                        // linkSpacing: 10,  //** not supported in v3.0
                        // packOption: go.LayeredDigraphLayout.PackAll,
                        columnSpacing: 10,  //** should be smaller than the default value of 25
                        commitLayers: function (layerRects, offset) {
                            // method override requires function, not =>
                            if (layerRects.length === 0) return;

                            var horiz = this.direction === 0 || this.direction === 180;
                            var forwards = this.direction === 0 || this.direction === 90;

                            var rect = layerRects[forwards ? layerRects.length - 1 : 0];
                            var totallength = horiz ? rect.right : rect.bottom;
                            if (horiz) {
                              offset.y -= this.columnSpacing*3/2;
                            } else {
                              offset.x -= this.columnSpacing*3/2;
                            }
                            for (var i = 0; i < this.laneNames.length; i++) {
                                var lane = this.laneNames[i];
                                // assume lane names do not conflict with node names
                                var group = this.diagram.findNodeForKey(lane);
                                if (group === null) {
                                    this.diagram.model.addNodeData({ key: lane, isGroup: true });
                                    group = this.diagram.findNodeForKey(lane);
                                }
                                //** Added this shift for all lanes
                                if (horiz) {
                                    group.location = new go.Point(-this.layerSpacing / 2, this.lanePositions.get(lane) * this.columnSpacing + offset.y);
                                } else {
                                    group.location = new go.Point(this.lanePositions.get(lane) * this.columnSpacing + offset.x, -this.layerSpacing / 2);
                                }
                                var ph = group.findObject('PLACEHOLDER'); // won't be a go.Placeholder, but just a regular Shape
                                if (ph === null) ph = group;
                                if (horiz) {
                                    ph.desiredSize = new go.Size(totallength, (this.laneBreadths.get(lane) * this.columnSpacing));
                                } else {
                                    ph.desiredSize = new go.Size(this.laneBreadths.get(lane) * this.columnSpacing, (totallength));
                                }
                            }
                        },
                    }),
                });

                myDiagram.nodeTemplate = $(go.Node, "Auto",
                    {
                        selectionAdorned: false,
                        movable: true,
                        selectionChanged: (part) => {
                            console.log(part)
                            //part.findNodesOutOf().each(n => n.fill = '#116173');
                            // const shape = part.elt(0);
                            // shape.fill = '#116173';
                        }
                    },
                    new go.Binding('location', 'loc', go.Point.parse),
                    go.Panel.Horizontal,
                    {
                        portId: '',
                        // fromLinkable: true, 
                        // toLinkable: true,
                        fromSpot: go.Spot.RightCenter,  // coming out from right side
                        toSpot: go.Spot.LeftCenter,   // g
                        click: (e, node) => {
                            //this.showHideNode(node)
                            console.log('ddd', e, node)
                        }
                    },
                    $(go.Panel,
                        go.Panel.Auto,
                        {
                            // click:(e, node) =>{
                            //   console.log('ddd', e, node)
                            // }
                        },
                        $(go.Shape, 'RoundedRectangle',
                            {
                                fill: 'white',
                                minSize: new go.Size(150, 100),
                                desiredSize: new go.Size(150, 100),
                                strokeWidth: 1,
                                //**margin: new go.Margin(40, 0),  //** Is this really needed???
                                //stretch: go.GraphObject.Horizontal,
                            },
                            { cursor: 'pointer' }, // indicate that linking may start here
                            new go.Binding('stroke', 'color'),
                            //new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),

                        ),
                        $(go.Panel,
                            'Horizontal',

                            $(go.TextBlock,
                                {
                                    margin: 2,
                                    stroke: '#4c525e',
                                    cursor: 'pointer',
                                    // stretch: go.GraphObject.Horizontal, 
                                    verticalAlignment: go.Spot.LeftCenter,
                                    textAlign: 'left',
                                    overflow: go.TextBlock.OverflowEllipsis,
                                    wrap: go.TextBlock.None,
                                    desiredSize: new go.Size(140, 25),
                                },
                                { fromLinkable: false, toLinkable: false }, // don't start drawing a link from the text
                                new go.Binding('text', 'text'),
                                new go.Binding('stroke', 'color')
                            ),

                        ),
                    ),
                    { // Tooltip for showing full text on hover
                        toolTip: $(go.Adornment, "Auto",
                            $(go.Shape, { fill: "#ffffff" }),
                            $(go.TextBlock, { margin: 4 },
                                new go.Binding("text", "text"))
                        )
                    },
                );





                myDiagram.nodeTemplateMap.add(
                    'ConditionStep',
                    $(go.Node,
                        'Auto',
                        { selectable: false, locationObjectName: "DiamondShape" },
                        // new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
                        $(go.Panel, "Vertical",
                            // { margin: new go.Margin(40, 0) },
                            // { defaultAlignment: go.Spot.Left },
                            $(go.Panel, "Auto",
                                // { defaultAlignment: go.Spot.Top, defaultStretch: go.GraphObject.Vertical, },
                                $(go.Shape, 'Diamond', {
                                    name: "DiamondShape",
                                    strokeWidth: .5,
                                    margin: new go.Margin(50, 0, 0, 0),
                                    // fill: "#F4B9B8",
                                    fill: "#FFFFC2",
                                    stroke: '#F79489',
                                    desiredSize: new go.Size(80, 80),
                                    // fromLinkable: false,
                                    // toLinkable: false,
                                    // fromLinkableDuplicates: false,
                                    // toLinkableDuplicates: false,
                                    // fromSpot: go.Spot.Right,
                                    // toSpot: go.Spot.Left,
                                    portId: "",
                                    // fromSpot: go.Spot.AllSides,
                                    // toSpot: go.Spot.AllSides,
                                    cursor: "pointer",
                                    // minSize: new go.Size(150, 100),
                                    // desiredSize: new go.Size(150, 100),
                                }, new go.Binding('margin', 'text', (text) => {
                                    console.log(text);
                                    console.log(text.length);
                                    if (text.length < 25) {
                                        return new go.Margin(20, 0, 0, 0)
                                    }
                                    if (text.length > 25 && text.length < 50) {
                                        return new go.Margin(40, 0, 0, 0)
                                    }
                                    if (text.length > 50) {
                                        return new go.Margin(50, 0, 0, 0)
                                    }
                                })

                                ),
                                $(go.Panel, "Horizontal",
                                    $(go.Panel, "Horizontal",
                                        // { alignment: go.Spot.Right },
                                        $(go.TextBlock,
                                            new go.Binding('text', 'text', (text) => {
                                                console.log(text);
                                                return "IF";
                                            })
                                        ),
                                    ),

                                    $(go.Panel, "Horizontal",
                                        // { alignment: go.Spot.Right },
                                        $(go.Panel, "Spot",
                                            { width: 45, height: 30 },
                                            { margin: new go.Margin(7, -25, 0, 5) },
                                            $(go.Shape, "Circle",
                                                // { alignment: go.Spot.Right },
                                                { fill: "white", stroke: "#C3BC00", desiredSize: new go.Size(20, 20) }
                                            ),
                                            $(go.TextBlock,
                                                { textAlign: "center" },
                                                // { verticalAlignment: go.Spot.Center },
                                                new go.Binding('text', 'text', (text) => {
                                                    console.log(text);
                                                    return "4";
                                                })
                                            )
                                        )
                                    )
                                ),

                                {
                                    toolTip: $(go.Adornment, "Auto",
                                        $(go.Shape, { fill: "#FFFFCC" }),
                                        $(go.TextBlock, { margin: 4 },
                                            new go.Binding("text", "text"))
                                    )
                                },
                            ),
                            // $(go.Panel, "Auto", { alignment: go.Spot.Center, desiredSize: new go.Size(180, 40), },
                            $(go.Panel, "Auto", { alignment: go.Spot.Center },
                                { margin: new go.Margin(10, 0, 0, 0) },
                                $(go.TextBlock,
                                    {
                                        maxLines: 3,
                                        overflow: go.TextBlock.OverflowEllipsis,
                                        // wrap: go.TextBlock.None,
                                        alignment: go.Spot.Center,
                                        font: '15px Inter, sans-serif',
                                        maxSize: new go.Size(200, NaN), // Restrict the width
                                        margin: 3,
                                        cursor: "pointer",
                                    },
                                    new go.Binding('text', 'key')),
                            )
                        ),
                    ),
                );








                myDiagram.linkTemplate = $(go.Link, // the whole link panel
                    {
                        routing: go.Link.AvoidsNodes,
                        curve: go.Curve.JumpOver,
                        corner: 0,
                        fromEndSegmentLength: 30,  //** to force links to go farther around
                        toEndSegmentLength: 30
                    },
                    $(go.Shape, // the link shape
                        { strokeWidth: 1.5, stroke: '#116173' },
                        new go.Binding('stroke', 'textnew', (textnew) => {
                            if (textnew !== '' && textnew !== 'Yes') {
                                return '#FF0404';
                            } else if (textnew === 'Yes') {
                                return '#00B66A';
                            }
                            return '#116173'; // default color
                        })
                    ),
                    $(go.Shape, // the arrowhead
                        { toArrow: 'Standard', stroke: 'lightblue' }
                    ),





                    $(go.Panel, "Auto",
                    {
                        segmentIndex: 0, segmentOffset: new go.Point(NaN, NaN),
                            segmentOrientation: go.Orientation.Upright
                    },
                        new go.Binding("visible", "textnew", (textnew) => textnew == "" ? false : true).makeTwoWay(),
                        $(go.Shape, "RoundedRectangle", // the rounded rectangle shape
                            { fill: "#E0FFF2", stroke: "#00B66A", strokeWidth: 1.5 },
                            { segmentIndex: 0 },

                            new go.Binding('stroke', 'textnew', (textnew) => {
                                if (textnew !== '' && textnew !== 'Yes') {
                                    return '#FF0404';
                                } else if (textnew === 'Yes') {
                                    return '#00B66A';
                                }
                                return '#116173'; // default color
                            }),
                            new go.Binding('fill', 'textnew', (textnew) => {
                                if (textnew !== '' && textnew !== 'Yes') {
                                    return '#FFE4E4';
                                } else if (textnew === 'Yes') {
                                    return '#E0FFF2';
                                }
                                return '#116173'; // default color
                            })
                        ),

                        $(go.TextBlock,
                            {
                                font: '9pt Figtree, sans-serif',
                                margin: 3,
                                editable: true,
                                segmentIndex: 0,
                                segmentOrientation: go.Orientation.Upright
                            },
                            new go.Binding("text", "textnew").makeTwoWay()
                        )
                    ),



                    new go.Binding("fromSpot", "textnew", (textnew) => textnew === '' ? go.Spot.Right : (textnew === "Yes" ? go.Spot.Right : go.Spot.Top)).makeTwoWay(),
                    new go.Binding("toSpot", "textnew", (textnew) => textnew === '' ? go.Spot.Left : (textnew === "Yes" ? go.Spot.Left : go.Spot.Top)).makeTwoWay()
                );




                myDiagram.groupTemplate = // assumes SwimLaneLayout.direction === 0
                    $(go.Group,
                        DIRECTION === 0 || DIRECTION === 180 ? 'Horizontal' : 'Vertical',
                        {
                            layerName: 'Background', // always behind all regular nodes and links
                            movable: false, // user cannot move or copy any lanes
                            copyable: false,
                            locationObjectName: 'PLACEHOLDER', // this object will be sized and located by SwimLaneLayout
                            layout: null, // no lane lays out its member nodes
                            avoidable: false, // don't affect any AvoidsNodes link routes,
                        },
                        $(go.TextBlock, { font: 'bold 12px sans-serif', angle: DIRECTION === 0 || DIRECTION === 180 ? 270 : 0 }, new go.Binding('text', 'text')),
                        $(go.Panel,
                            'Auto',
                            $(go.Shape, { fill: 'transparent', stroke: 'orange' }),
                            $(go.Shape, { name: 'PLACEHOLDER', fill: null, stroke: null, strokeWidth: 0, }),
                            // $(go.TextBlock, { font: 'bold 12pt sans-serif'}, new go.Binding('text', 'text')),
                        ),
                        // $(go.TextBlock, { font: 'bold 12pt sans-serif', angle: DIRECTION === 0 || DIRECTION === 180 ? 90 : 0 }, new go.Binding('text', 'text'))
                    );

                partitionBy('d');
            }

            // the array of node data describing each team, each division, and each conference

            const newDataSet =
                [
                    {
                        "key": "start_node",
                        "text": "Start",
                        "category": "start_node",
                        "group": "cp",
                    },
                    {
                        "key": "end_node",
                        "text": "End",
                        "category": "end_node",
                        "group": "hp",
                    },
                    {
                        "key": "A",
                        "text": "A",
                        "category": "BusinessStep",
                        "group": "hp",
                    },
                    {
                        "key": "B",
                        "text": "B",
                        "category": "BusinessStep",
                        "group": "a",
                    },
                    {
                        "key": "H",
                        "text": "H",
                        "category": "BusinessStep",
                        "group": "a",
                    },
                    {
                        "key": "C",
                        "text": "C",
                        "category": "BusinessStep",
                        "group": "a",
                    },
                    {
                        "key": "DhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghg",
                        "text": "DhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghg",
                        "category": "ConditionStep",
                        "group": "a",
                    },
                    {
                        "key": "DhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgD",
                        "text": "DhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgD",
                        "category": "ConditionStep",
                        "group": "a",
                    },
                    {
                        "key": "E",
                        "text": "E",
                        "category": "BusinessStep",
                        "group": "hp",
                    },
                    {
                        "key": "cp",
                        "text": "cp",
                        "category": "Lane",
                        "isGroup": true
                    },
                    {
                        "key": "a",
                        "text": "a",
                        "category": "Lane",
                        "isGroup": true
                    },
                    {
                        "key": "hp",
                        "text": "hp",
                        "category": "Lane",
                        "isGroup": true
                    }
                ];

            const newLinkData =
                [
                    {
                        "from": "start_node",
                        "to": "A",
                        "textnew": ""
                    },
                    {
                        "from": "E",
                        "to": "end_node",
                        "textnew": ""
                    },
                    {
                        "from": "A",
                        "to": "B",
                        "textnew": ""
                    },
                    {
                        "from": "B",
                        "to": "DhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghg",
                        "textnew": ""
                    },
                    {
                        "from": "B",
                        "to": "H",
                        "textnew": ""
                    },
                    {
                        "from": "H",
                        "to": "DhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghg",
                        "textnew": ""
                    },
                    {
                        "from": "DhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghg",
                        "to": "DhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgD",
                        "textnew": "No"
                    },
                    {
                        "from": "DhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghg",
                        "to": "C",
                        "textnew": "Yes"
                    },
                    {
                        "from": "C",
                        "to": "DhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgD",
                        "textnew": ""
                    },
                    {
                        "from": "DhghgDhghgDhghgDhghgDhghgDhghgDhghgDhghgD",
                        "to": "E",
                        "textnew": ""
                    }
                ]

            function getNodeStrokeColor(subcategory) {
                console.log(subcategory);
                if (subcategory == 'Yes') {
                    return 'red'
                }
                // return subcategory == 'Yes' ? 'red'
                // return this.subcategoryColorsStroke[subcategory] || '#17E09A'; // Default color if subcategory is not defined
            }



            // the array of link data objects: the relationships between the nodes

            function partitionBy(a) {
                // create the model and assign it to the Diagram
                var model = new go.GraphLinksModel();
                // depending on how we are partitioning the graph, each node belongs either
                // to a conference group or to a division group
                model.nodeGroupKey = a === 'c' ? 'conf' : 'group';
                model.nodeDataArray = newDataSet;
                model.linkDataArray = newLinkData;
                // each node's lane information is the same as the group information
                myDiagram.layout.laneProperty = model.nodeGroupKey;
                // optionally, specify the order of known lane names, without setting laneComparer
                //myDiagram.layout.laneNames = a === 'c' ? ['AFC', 'NFC'] : ['AFCE', 'AFCN', 'AFCS', 'AFCW', 'NFCE', 'NFCN', 'NFCS', 'NFCW'];
                myDiagram.model = model;
            }
            window.addEventListener('DOMContentLoaded', init);
        </script>

        <div id="sample">
            <!-- <p><b>Beat Paths</b>: The 2007 NFL Season, divided by conference or by division</p> -->
            <div id="myDiagramDiv"
                style="border: 1px solid gray; margin: 10px; height: 100vh; position: relative; -webkit-tap-highlight-color: rgba(255, 255, 255, 0);">
                <canvas tabindex="0" width="1226" height="698"
                    style="position: absolute; top: 0px; left: 0px; z-index: 2; user-select: none; touch-action: none; width: 1226px; height: 698px;"></canvas>
                <div style="position: absolute; overflow: auto; width: 1226px; height: 698px; z-index: 1;">
                    <div style="position: absolute; width: 1px; height: 1px;"></div>
                </div>
            </div>
            <input type="radio" name="A" onclick="partitionBy('c')" id="conferenceButton">
            <label for="conferenceButton">Conferences</label><br>
            <input type="radio" name="A" onclick="partitionBy('d')" id="divisionButton" checked="">
            <label for="divisionButton">Divisions</label><br>
        </div>
</body>

</html>

And here’s the modification of the SwimLaneLayout.ts file that you need to make, if you are using TypeScript. Just replace this method:

  private compareVertexes(v: go.LayeredDigraphVertex, w: go.LayeredDigraphVertex) {
    let laneV = this.findLane(v);
    if (laneV === null) laneV = '';
    let laneW = this.findLane(w);
    if (laneW === null) laneW = '';
    if (laneV < laneW) return -1;
    if (laneV > laneW) return 1;
    // sort dummy vertexes before vertexes representing real nodes
    if (v.node === null && w.node !== null) return -1;
    if (v.node !== null && w.node === null) return 1;
    if (v.column < w.column) return -1;
    if (v.column > w.column) return 1;
    return 0;
  }

And here’s the compiled JavaScript:

    compareVertexes(v, w) {
        let laneV = this.findLane(v);
        if (laneV === null)
            laneV = '';
        let laneW = this.findLane(w);
        if (laneW === null)
            laneW = '';
        if (laneV < laneW)
            return -1;
        if (laneV > laneW)
            return 1;
        // sort dummy vertexes before vertexes representing real nodes
        if (v.node === null && w.node !== null)
            return -1;
        if (v.node !== null && w.node === null)
            return 1;
        if (v.column < w.column)
            return -1;
        if (v.column > w.column)
            return 1;
        return 0;
    }

I am take swimlane layout file from here

and use in my code as you done changes in layout and change your given function but currenly also face same issue

Link if spot from top then link from top to top connect then only connect to top means not take largest path

if from top fromspot and top tospot then link goes from above node but as you see that in image this goes from bottom to node pls do something for that issue , this issue is not resolve as you mention above pls do something

Before I made the above listed changes to your code and to the SwimLaneLayout, I reproduced your results. With my changes, I no longer have that problem.

Thanks sir , here above link is come but face some issue

Sir how can I remove this in link bends I want straight link because here curviness is not required , here direct (straight ) link is as in previous example

And here below is previous example image attached

Sir how can I do this red line straight as you see in image this is bended and this bend is not required , this is irrelevant

You can try reducing the columnSpacing, but in general there’s no guarantee that links will form straight lines.