Selection in Field items

Hi Walter,

As you mentioned functionality in Mapping Selectable Fields of Records .

Its working fine. I want to a small change in this articles when user select other item then previous automatic unselect. Currently we have to click again to make unselect.

You can change the click event handler to deselect all of the other fields in the node.

I can improve the sample later today.

Thanks walter, Please share an example.

    function init() {

      // Since 2.2 you can also author concise templates with method chaining instead of GraphObject.make
      // For details, see https://gojs.net/latest/intro/buildingObjects.html
      const $ = go.GraphObject.make;  // for conciseness in defining templates

      myDiagram =
        $(go.Diagram, "myDiagramDiv",
          {
            validCycle: go.Diagram.CycleNotDirected,  // don't allow loops
            // For this sample, automatically show the state of the diagram's model on the page
            "ModelChanged": e => {
              if (e.isTransactionFinished) showModel();
            },
            "undoManager.isEnabled": true
          });

      const UnselectedBrush = "transparent";  // item appearance, if not "selected"
      const SelectedBrush = "dodgerblue";   // item appearance, if "selected"

      function isFieldSelected(item) {
        return item.background !== UnselectedBrush;
      }

      function setFieldSelected(item, sel) {
        if (sel) {
          item.background = SelectedBrush;
        } else {
          item.background = UnselectedBrush;
        }
      }

      function onFieldClick(e, item) {
        var oldskips = item.diagram.skipsUndoManager;
        item.diagram.skipsUndoManager = true;
        if (e.control || e.meta) {
          setFieldSelected(item, !isFieldSelected(item));
          item.part.isSelected = item.panel.elements.any(isFieldSelected);
        } else if (e.shift) {
          // alternative policy: select all fields between this item and some other one??
          if (!isFieldSelected(item)) setFieldSelected(item, true);
          item.part.isSelected = true;
        } else {
          if (!isFieldSelected(item)) {
            // deselect all sibling items
            item.panel.elements.each(it => {
              if (it !== item) setFieldSelected(it, false);
            });
            setFieldSelected(item, true);
          }
          item.part.isSelected = true;
        }
        item.diagram.skipsUndoManager = oldskips;
      }

      // This template is a Panel that is used to represent each item in a Panel.itemArray.
      // The Panel is data bound to the item object.
      var fieldTemplate =
        $(go.Panel, "TableRow",  // this Panel is a row in the containing Table
          new go.Binding("portId", "name"),  // this Panel is a "port"
          {
            background: UnselectedBrush,  // so this port's background can be picked by the mouse
            fromSpot: go.Spot.LeftRightSides,  // links only go from the right side to the left side
            toSpot: go.Spot.LeftRightSides,
            // allow drawing links from or to this port:
            fromLinkable: true, toLinkable: true
          },
          { // select items -- the background indicates "selected" when not UnselectedBrush
            click: onFieldClick
          },
          $(go.Shape,
            {
              width: 12, height: 12, column: 0, strokeWidth: 2, margin: 4,
              // but disallow drawing links from or to this shape:
              fromLinkable: false, toLinkable: false
            },
            new go.Binding("figure", "figure"),
            new go.Binding("fill", "color")),
          $(go.TextBlock,
            {
              margin: new go.Margin(0, 2), column: 1, font: "bold 13px sans-serif",
              // and disallow drawing links from or to this text:
              fromLinkable: false, toLinkable: false
            },
            new go.Binding("text", "name")),
          $(go.TextBlock,
            { margin: new go.Margin(0, 2), column: 2, font: "13px sans-serif" },
            new go.Binding("text", "info"))
        );

      // This template represents a whole "record".
      myDiagram.nodeTemplate =
        $(go.Node, "Auto",
          new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
          // this rectangular shape surrounds the content of the node
          $(go.Shape,
            { fill: "#EEEEEE" }),
          // the content consists of a header and a list of items
          $(go.Panel, "Vertical",
            // this is the header for the whole node
            $(go.Panel, "Auto",
              { stretch: go.GraphObject.Horizontal },  // as wide as the whole node
              $(go.Shape,
                { fill: "#1570A6", stroke: null }),
              $(go.TextBlock,
                {
                  alignment: go.Spot.Center,
                  margin: 3,
                  stroke: "white",
                  textAlign: "center",
                  font: "bold 12pt sans-serif"
                },
                new go.Binding("text", "key"))),
            // this Panel holds a Panel for each item object in the itemArray;
            // each item Panel is defined by the itemTemplate to be a TableRow in this Table
            $(go.Panel, "Table",
              {
                name: "TABLE",
                padding: 2,
                minSize: new go.Size(100, 10),
                defaultStretch: go.GraphObject.Horizontal,
                itemTemplate: fieldTemplate
              },
              new go.Binding("itemArray", "fields")
            )  // end Table Panel of items
          )  // end Vertical Panel
        );  // end Node

      myDiagram.linkTemplate =
        $(go.Link,
          { relinkableFrom: true, relinkableTo: true, toShortLength: 4 },  // let user reconnect links
          $(go.Shape, { strokeWidth: 1.5 }),
          $(go.Shape, { toArrow: "Standard", stroke: null })
        );

      myDiagram.model =
        new go.GraphLinksModel(
          {
            copiesArrays: true,
            copiesArrayObjects: true,
            linkFromPortIdProperty: "fromPort",
            linkToPortIdProperty: "toPort",
            nodeDataArray: [
              {
                key: "Record1",
                fields: [
                  { name: "field1", info: "", color: "#F7B84B", figure: "Ellipse" },
                  { name: "field2", info: "the second one", color: "#F25022", figure: "Ellipse" },
                  { name: "fieldThree", info: "3rd", color: "#00BCF2" }
                ],
                loc: "0 0"
              },
              {
                key: "Record2",
                fields: [
                  { name: "fieldA", info: "", color: "#FFB900", figure: "Diamond" },
                  { name: "fieldB", info: "", color: "#F25022", figure: "Rectangle" },
                  { name: "fieldC", info: "", color: "#7FBA00", figure: "Diamond" },
                  { name: "fieldD", info: "fourth", color: "#00BCF2", figure: "Rectangle" }
                ],
                loc: "250 0"
              }
            ],
            linkDataArray: [
              { from: "Record1", fromPort: "field1", to: "Record2", toPort: "fieldA" },
              { from: "Record1", fromPort: "field2", to: "Record2", toPort: "fieldD" },
              { from: "Record1", fromPort: "fieldThree", to: "Record2", toPort: "fieldB" }
            ]
          });

      // this is a bit inefficient, but should be OK for normal-sized graphs with reasonable numbers of items per node
      function findAllSelectedItems() {
        var items = [];
        for (var nit = myDiagram.nodes; nit.next();) {
          var node = nit.value;
          var table = node.findObject("TABLE");
          if (table) {
            for (var iit = table.elements; iit.next();) {
              var itempanel = iit.value;
              if (isFieldSelected(itempanel)) items.push(itempanel);
            }
          }
        }
        return items;
      }

      // Override the standard CommandHandler deleteSelection behavior.
      // If there are any selected items, delete them instead of deleting any selected nodes or links.
      myDiagram.commandHandler.canDeleteSelection = function() {
        // true if there are any selected deletable nodes or links,
        // or if there are any selected items within nodes
        return go.CommandHandler.prototype.canDeleteSelection.call(myDiagram.commandHandler) ||
          findAllSelectedItems().length > 0;
      };

      myDiagram.commandHandler.deleteSelection = function() {
        var items = findAllSelectedItems();
        if (items.length > 0) {  // if there are any selected items, delete them
          myDiagram.startTransaction("delete items");
          for (var i = 0; i < items.length; i++) {
            var panel = items[i];
            var nodedata = panel.part.data;
            var itemarray = nodedata.fields;
            var itemdata = panel.data;
            var itemindex = itemarray.indexOf(itemdata);
            myDiagram.model.removeArrayItem(itemarray, itemindex);
          }
          myDiagram.commitTransaction("delete items");
        } else {  // otherwise just delete nodes and/or links, as usual
          go.CommandHandler.prototype.deleteSelection.call(myDiagram.commandHandler);
        }
      };

      showModel();  // show the diagram's initial model

      function showModel() {
        document.getElementById("mySavedModel").textContent = myDiagram.model.toJson();
      }
    }
    window.addEventListener('DOMContentLoaded', init);