Padding in the table layout

I am using table layout and i want to add the padding in the table
image
like this.
How can i do that ?
I am using table layout extension file.

Is that a Group holding those nine nodes? How have you defined that Group?

Yes i am using group

this.diagram.groupTemplateMap.add(templateName, $(go.Group, 'Auto',
            {
                layerName: 'Background',
                stretch: go.GraphObject.Fill,
                selectable: false,
                computesBoundsAfterDrag: false,
                computesBoundsIncludingLocation: true,
                handlesDragDropForMembers: false,  // don't need to define handlers on member Nodes and Links
                mouseDragEnter: function (e: go.InputEvent, group: any, prev: go.GraphObject) { group.isHighlighted = true; },
                mouseDragLeave: function (e: go.InputEvent, group: any, next: go.GraphObject) { group.isHighlighted = false; },
                mouseDrop: (e, obj) => this.gridColumnTemplateMouseDropHandler(e, obj)
            },
            new go.Binding('row'),
            new go.Binding('column', 'col'),
            $(go.Shape,
                {
                    strokeWidth: 1,
                    fill: 'white',
                    stretch: go.GraphObject.Fill,
                    width: 100,
                    height: 100,
                },
                new go.Binding('stroke', 'isHighlighted', function (h) { return h ? 'red' : 'lightgray'; }).ofObject()),
            $(go.TextBlock,
                {
                    alignment: go.Spot.Center, width: 80, textAlign: 'center',
                    wrap: go.TextBlock.WrapDesiredSize, stroke: 'gray', text: CONSTANTS.DragAndDropBin,
                    font: 'italic 8pt Verdana', name: CONSTANTS.DIAGRAM.DRAG_AND_DROP_NAME
                },
                new go.Binding('visible', 'hasData', data => !data)
            ),
            $(go.TextBlock, {
                alignment: go.Spot.BottomCenter, margin: new go.Margin(0, 0, 10, 0),
                textAlign: 'center', wrap: go.TextBlock.WrapDesiredSize, stroke: '#0a599c', text: '+',
                font: 'bold 14pt Verdana', name: CONSTANTS.DIAGRAM.SKU_PLUS_NAME
            },
                new go.Binding('visible', 'hasData', data => !data)
            ),
        ));```

No, I was asking about the Part holding that outer border.
Presumably its Group.layout is that TableLayout.
Are you expecting that border to contract/expand as those nodes are added or removed or moved?

Or did you not want to design that outer Part to be a Group because you don’t want those nine nodes to be members of that group?

I really cannot tell what requirements you have and thus I cannot suggest what might be a good design.

So there are two layers
image
behind this there is one more group nodes code is almost same which i given.
And this Drag & Drop SKU/Bin is node above that node.

// Groups Template
this.setupDefaultGroupTemplate();
this.setupGridColumnContainerTemplate();

Calling these function on initialization.
So i want to add padding around the diagram.

The group template that you provided is the definition of those “Drag & Drop SKU / Bin” nodes, yes? But that wasn’t what I was asking about. What is the definition of that border that you want to be around those nine nodes?

And you haven’t answered my question whether those nine “Drag & Drop SKU / BIn” nodes are members of a group or not. And if they are, whether or not the group template should use a Placeholder or not.

This is the current implementation
image
Now i want to make it look like this ,currently there is no border , the image i had attached is of UI/UX.
image
How can i add that border or padding around the corners.
And yes the group template i provided is the definition of drag and drop sku bin.
BY placeholder what do you mean?
I am new to gojs

In that screenshot are you showing a background grid with thick white lines on a light blue background?

yes that’s a background grid with thick white lines

grid: $(go.Panel, 'Grid',
                        {
                            gridCellSize: CellSize,
                        },
                        $(go.Shape, 'LineH', { stroke: '#C9E2F8', strokeWidth: 13 }),
                        $(go.Shape, 'LineV', { stroke: '#ffffff', strokeWidth: 4 }),
                    )

What about my other questions?

There are two group templates, one is default and one is Grid cell and this drag and drop is in grid cell template.
There is a group template behind this which is empty white color as we can drag and drop the cell to other sell. So i want to add the thick border in all the four corner and it will be dynamic as there can be n rows and m columns.

How to add border around this table layout

<!DOCTYPE html>
<html>

<head>
  <title>Simple Table with Empty Slots</title>
  <!-- Copyright 1998-2023 by Northwoods Software Corporation. -->
</head>

<body>
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
  <textarea id="mySavedModel" style="width:100%;height:300px">
{ "class": "GraphLinksModel",
  "nodeDataArray": [
{"key":1,"text":"Alpha","color":"lightblue","row":0,"col":0},
{"key":2,"text":"Beta","color":"orange","row":0,"col":1},
{"key":3,"text":"Gamma","color":"lightgreen","row":1,"col":0},
{"key":4,"text":"Delta","color":"pink","row":1,"col":1},
{"key":5,"text":"Epsilon","color":"lightblue","row":1,"col":3},
{"key":6,"text":"Zeta","color":"orange","row":2,"col":2},
{"key":7,"text":"Eta","color":"lightgreen","row":0,"col":3},
{"key":8,"text":"Theta","color":"pink","row":3,"col":1},
{"key":9,"text":"Iota","color":"lightblue","row":3,"col":3},
{"key":10,"text":"Kappa","color":"orange","row":2,"col":5},
{"key":11,"text":"Lambda","color":"lightgreen","row":2,"col":4},
{"key":12,"text":"Mu","color":"pink","row":2,"col":0},
{"category":"Empty","row":0,"col":2},
{"category":"Empty","row":0,"col":4},
{"category":"Empty","row":0,"col":5},
{"category":"Empty","row":1,"col":2},
{"category":"Empty","row":1,"col":4},
{"category":"Empty","row":1,"col":5},
{"category":"Empty","row":2,"col":1},
{"category":"Empty","row":2,"col":3},
{"category":"Empty","row":3,"col":0},
{"category":"Empty","row":3,"col":2},
{"category":"Empty","row":3,"col":4},
{"category":"Empty","row":3,"col":5}
]}
  </textarea>

  <script src="https://unpkg.com/gojs"></script>
  <script src="https://gojs.net/latest/extensions/TableLayout.js"></script>
  <script id="code">
    const $ = go.GraphObject.make;

    const CELLW = 120;
    const CELLH = 120;
    const TABLEW = 6;
    const TABLEH = 4;

    const myDiagram =
      new go.Diagram("myDiagramDiv",
        {
          layout: $(TableLayout),
          "draggingTool.isGridSnapEnabled": true,
          "draggingTool.gridSnapCellSize": new go.Size(CELLW, CELLH),
          "draggingTool.gridSnapCellSpot": go.Spot.Center,
          "SelectionMoved": e => {  // update the data.row and .col
            e.subject.each(node => {
              const oldrow = node.data.row || 0;
              const oldcol = node.data.col || 0;
              const row = Math.floor(node.location.y / CELLH);
              const col = Math.floor(node.location.x / CELLW);
              const oldpart = findPartAt(row, col);
              const m = e.diagram.model;
              if (oldpart && oldpart.category === "Empty") {
                m.set(node.data, "row", row);
                m.set(node.data, "col", col);
                m.set(oldpart.data, "row", oldrow);
                m.set(oldpart.data, "col", oldcol);
              }
              // else don't move this node!  the layout will move it back
            });
            e.diagram.layout.invalidateLayout();
          },
          "SelectionCopied": e => {  // update the data.row and .col
            e.subject.each(node => {
              const row = Math.floor(node.location.y / CELLH);
              const col = Math.floor(node.location.x / CELLW);
              const oldpart = findPartAtRowCol(row, col);
              const m = e.diagram.model;
              if (oldpart && oldpart.category === "Empty") {
                m.removeNodeData(oldpart.data);
                m.set(node.data, "row", row);
                m.set(node.data, "col", col);
              }
            });
            e.diagram.layout.invalidateLayout();
          },
          "undoManager.isEnabled": true,
          "ModelChanged": e => {     // just for demonstration purposes,
            if (e.isTransactionFinished) {  // show the model data in the page's TextArea
              document.getElementById("mySavedModel").textContent = e.model.toJson();
            }
          }
        });

    // don't use the infinite Diagram.grid, but just a fixed, limited grid in the "Grid" layer
    myDiagram.add(
      $(go.Part, "Grid",
        { layerName: "Grid", position: new go.Point(0, 0) },
        { width: TABLEW * CELLW + 1, height: TABLEH * CELLH + 1, gridCellSize: new go.Size(CELLW, CELLH) },
        $(go.Shape, "LineH", { stroke: "gray" }),
        $(go.Shape, "LineV", { stroke: "gray" })
      ));

    // look up the Node or Empty Part that is at a particular row/column
    function findPartAt(r, c) {
      const a = myDiagram.model.nodeDataArray;
      for (let i = 0; i < a.length; i++) {
        if (a[i].row === r && a[i].col === c) return myDiagram.findPartForData(a[i]);
      }
      return null;
    }

    myDiagram.nodeTemplate =
      $(go.Node, "Auto",
        {
          width: CELLW, height: CELLH,
          locationSpot: go.Spot.Center,
          minLocation: new go.Point(CELLW / 2, CELLH / 2),  // don't let nodes be moved beyond the table
          maxLocation: new go.Point(TABLEW * CELLW - CELLW / 2, TABLEH * CELLH - CELLH / 2)
        },
        new go.Binding("row"),
        new go.Binding("column", "col"),
        new go.Binding("layerName", "isSelected", s => s ? "Foreground" : "").ofObject(),
        $(go.Shape,
          { fill: "white", stroke: null },
          new go.Binding("fill", "color")),
        $(go.TextBlock,
          new go.Binding("text"))
      );

    myDiagram.nodeTemplateMap.add("Empty",
      $(go.Part, "Auto",
        { width: CELLW, height: CELLH, locationSpot: go.Spot.Center, layerName: "Background" },
        { selectable: false, movable: false, copyable: false, deletable: false },
        new go.Binding("row"),
        new go.Binding("column", "col"),
        $(go.Shape,
          { fill: "white", stroke: null, pickable: false }),
        $(go.TextBlock, "Drag & Drop\nSKU / Bin",
          { stroke: "gray", font: "italic 12pt sans-serif", textAlign: "center" })
      ));

    myDiagram.model = go.Model.fromJson(document.getElementById("mySavedModel").textContent);
  </script>
</body>

</html>

I simply added a border around the “Grid” Panel.

I also fixed a bug when copying.

<!DOCTYPE html>
<html>
<head>
  <title>Simple Table with Empty Slots</title>
  <!-- Copyright 1998-2023 by Northwoods Software Corporation. -->
</head>
<body>
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
  <textarea id="mySavedModel" style="width:100%;height:400px">
{ "class": "GraphLinksModel",
  "nodeDataArray": [
{"key":1,"text":"Alpha","color":"lightblue","row":0,"col":0},
{"key":2,"text":"Beta","color":"orange","row":0,"col":1},
{"key":3,"text":"Gamma","color":"lightgreen","row":1,"col":0},
{"key":4,"text":"Delta","color":"pink","row":1,"col":1},
{"key":5,"text":"Epsilon","color":"lightblue","row":1,"col":3},
{"key":6,"text":"Zeta","color":"orange","row":2,"col":2},
{"key":7,"text":"Eta","color":"lightgreen","row":0,"col":3},
{"key":8,"text":"Theta","color":"pink","row":3,"col":1},
{"key":9,"text":"Iota","color":"lightblue","row":3,"col":3},
{"key":10,"text":"Kappa","color":"orange","row":2,"col":5},
{"key":11,"text":"Lambda","color":"lightgreen","row":2,"col":4},
{"key":12,"text":"Mu","color":"pink","row":2,"col":0},
{"category":"Empty","row":0,"col":2},
{"category":"Empty","row":0,"col":4},
{"category":"Empty","row":0,"col":5},
{"category":"Empty","row":1,"col":2},
{"category":"Empty","row":1,"col":4},
{"category":"Empty","row":1,"col":5},
{"category":"Empty","row":2,"col":1},
{"category":"Empty","row":2,"col":3},
{"category":"Empty","row":3,"col":0},
{"category":"Empty","row":3,"col":2},
{"category":"Empty","row":3,"col":4},
{"category":"Empty","row":3,"col":5}
]}
  </textarea>

  <script src="https://cdn.jsdelivr.net/npm/gojs/release/go.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/create-gojs-kit/dist/extensions/TableLayout.js"></script>
  <script id="code">
const CELLW = 120;
const CELLH = 120;
const TABLEW = 6;
const TABLEH = 4;

const myDiagram =
  new go.Diagram("myDiagramDiv", {
      layout: new TableLayout(),
      "draggingTool.isGridSnapEnabled": true,
      "draggingTool.gridSnapCellSize": new go.Size(CELLW, CELLH),
      "draggingTool.gridSnapCellSpot": go.Spot.Center,
      "SelectionMoved": e => {  // update the data.row and .col
        e.subject.each(node => {
          const oldrow = node.data.row || 0;
          const oldcol = node.data.col || 0;
          const row = Math.floor(node.location.y / CELLH);
          const col = Math.floor(node.location.x / CELLW);
          const oldpart = findPartAt(row, col);
          const m = e.diagram.model;
          if (oldpart && oldpart.category === "Empty") {
            m.set(node.data, "row", row);
            m.set(node.data, "col", col);
            m.set(oldpart.data, "row", oldrow);
            m.set(oldpart.data, "col", oldcol);
          }
          // else don't move this node!  the layout will move it back
        });
        e.diagram.layout.invalidateLayout();
      },
      "SelectionCopied": e => {  // update the data.row and .col
        e.subject.each(node => {
          const row = Math.floor(node.location.y / CELLH);
          const col = Math.floor(node.location.x / CELLW);
          const oldpart = findPartAt(row, col);
          const m = e.diagram.model;
          if (oldpart && oldpart.category === "Empty") {
            m.removeNodeData(oldpart.data);
            m.set(node.data, "row", row);
            m.set(node.data, "col", col);
          } else {
            m.removeNodeData(node.data);  // undo copy of this node
          }
        });
        e.diagram.layout.invalidateLayout();
      },
      "undoManager.isEnabled": true,
      "ModelChanged": e => {     // just for demonstration purposes,
        if (e.isTransactionFinished) {  // show the model data in the page's TextArea
          document.getElementById("mySavedModel").textContent = e.model.toJson();
        }
      }
    });

// don't use the infinite Diagram.grid, but just a fixed, limited grid in the "Grid" layer
myDiagram.add(
  new go.Part("Auto", {
      layerName: "Grid",
      location: new go.Point(0, 0), locationObjectName: "GRID"
    })
    .add(
      new go.Shape({ fill: null, stroke: "blue", strokeWidth: 2 }),
      new go.Panel("Grid", {
          name: "GRID",
          width: TABLEW * CELLW + 1, height: TABLEH * CELLH + 1,
          gridCellSize: new go.Size(CELLW, CELLH),
          margin: 4
        })
        .add(
          new go.Shape("LineH", { stroke: "gray" }),
          new go.Shape("LineV", { stroke: "gray" })
        )
    ));

// look up the Node or Empty Part that is at a particular row/column
function findPartAt(r, c) {
  const a = myDiagram.model.nodeDataArray;
  for (let i = 0; i < a.length; i++) {
    if (a[i].row === r && a[i].col === c) return myDiagram.findPartForData(a[i]);
  }
  return null;
}

myDiagram.nodeTemplate =
  new go.Node("Auto", {
      width: CELLW, height: CELLH,
      locationSpot: go.Spot.Center,
      minLocation: new go.Point(CELLW / 2, CELLH / 2),  // don't let nodes be moved beyond the table
      maxLocation: new go.Point(TABLEW * CELLW - CELLW / 2, TABLEH * CELLH - CELLH / 2)
    })
    .bind("row")
    .bind("column", "col")
    .bindObject("layerName", "isSelected", s => s ? "Foreground" : "")
    .add(
      new go.Shape({ fill: "white", stroke: null })
        .bind("fill", "color"),
      new go.TextBlock()
        .bind("text")
    );

myDiagram.nodeTemplateMap.add("Empty",
  new go.Part("Auto", {
      width: CELLW, height: CELLH,
      locationSpot: go.Spot.Center,
      layerName: "Background",
      selectable: false, movable: false, copyable: false, deletable: false
    })
    .bind("row")
    .bind("column", "col")
    .add(
      new go.Shape({ fill: "white", stroke: null, pickable: false }),
      new go.TextBlock("Drag & Drop\nSKU / Bin", {
        stroke: "gray", font: "italic 12pt sans-serif", textAlign: "center"
      })
    ));

myDiagram.model = go.Model.fromJson(document.getElementById("mySavedModel").textContent);
  </script>
</body>
</html>