How to manage custom node rotation & group rotation?

How to manage custom node rotation & group rotation?
How to implement both node & group rotation using GroupRotatingTool.js?
Can you provide an example of that.
We check Rotating Groups. Here only group rotation is there.
We want both node & group rotation.

If Nodes have Node.rotatable set or bound to true, are they not rotatable by the user?

rotatable is set to true
We want to rotate node & group.
We implement rotate node

DrawCommandHandler.prototype.rotate = function(angle) {
  if (angle === undefined) angle = 90;
  var diagram = this.diagram;
  diagram.startTransaction("rotate " + angle.toString());
  var diagram = this.diagram;
  diagram.selection.each(function(current) {
    var shape = current.findObject("img");
    
    if (current instanceof go.Link) return; // skips over Links and Groups
    shape.angle += angle;
    jQuery('#'+current.data.ComponentNo+'--__--DiagramRotationAngle').val(shape.angle);
  });
  diagram.commitTransaction("rotate " + angle.toString());
}; 

We can not rotate group with all it’s node.

Please format your code, using surrounding lines of triple backquotes, so that I can read it.

If you expect to rotate the member nodes of groupsl you need to do that explicitly. That sample, Rotating Groups, does that.

rotatable is set to true
We want to rotate node & group.
We implement rotate node

DrawCommandHandler.prototype.rotate = function(angle) {
  console.log("angle:- "+angle);
  if (angle === undefined) angle = 90;
  var diagram = this.diagram;
  diagram.selection.each(function(current) {
    if(current.data.isGroup){
      console.log("group rotation");
    }else{
      diagram.startTransaction("rotate " + angle.toString());
      var shape = current.findObject("img");
      if (current instanceof go.Link) return; // skips over Links and Groups
      shape.angle += angle;
      diagram.commitTransaction("rotate " + angle.toString());
    }
    
  });
 
};

We can not rotate group with all it’s node.

We saw that example.there is only group rotation no node rotation. We need both.

If I set Node.rotatable to true in the node template of that GroupRotating sample, I as a user can rotate either simple Nodes or Groups. Including member nodes of nested groups. It makes use of the GroupRotatingTool.

rotatable is true for all nodes.
Can you please give me an example where both node rotations & group rotations are there?

I set { rotatable: true } on the node template in that GroupRotating.html sample.

Getting error “Error: GroupRotatingTool can’t handle Placeholder in Group”

myDiagram.groupTemplateMap.add("UserDefineGroup",
    $(go.Group, "Auto", {
            rotatable: true,
            rotateObjectName: "img", // rotate the Shape, not the Node
            locationSpot: go.Spot.Center,
            locationObjectName: "img",
            rotateAdornmentTemplate: // specify appearance of rotation handle
                $(go.Adornment, {
                        locationSpot: go.Spot.Center,
                        background: "transparent"
                    },
                    $(go.Shape, "BpmnActivityLoop", {
                        width: 12,
                        height: 12,
                        stroke: "dodgerblue",
                        strokeWidth: 2
                    })),
            selectionObjectName: "SHAPE"
        },
        new go.Binding("location", "pos", go.Point.parse).makeTwoWay(go.Point.stringify),
        {
            isSubGraphExpanded: true,
            ungroupable: true,
            subGraphExpandedChanged: function(group) {}
        },
        new go.Binding("isSubGraphExpanded", "isSubGraphExpanded"), {
            toolTip: myToolTips
        },
        $(go.Shape, "Rectangle", {
            fill: gbackground,
            stroke: null,
            spot1: go.Spot.TopLeft,
            spot2: go.Spot.BottomRight
        }, new go.Binding("stroke"), new go.Binding("fill")),
        $(go.Panel, "Vertical",
            $(go.TextBlock, "Center", {
                    name: "txt",
                    row: 0,
                    font: "6pt sans-serif",
                    wrap: go.TextBlock.WrapFit,
                    width: 60,
                    editable: true
                },
                new go.Binding("text")),
            $(go.Panel, "Table",
                $(go.Panel, "Table", {
                        name: "img",
                    },
                    $(go.Picture, gicon, {
                            visible: false,
                            row: 1,
                            width: 55,
                            height: 55,
                        },
                        new go.Binding("visible", "isSubGraphExpanded",
                            function(exp) {
                                return exp ? false : true;
                            }).ofObject(),
                    ),
                    $("SubGraphExpanderButton", {
                        row: 1
                    }),
                    $(go.Placeholder, {
                            row: 2,
                            padding: 5
                        },
                        new go.Binding("padding", "isSubGraphExpanded",
                            function(exp) {
                                return exp ? 10 : 0;
                            }).ofObject(),
                    ),
                ),
            ),
        ), {
            contextMenu: $(go.Adornment, "Vertical", {
                    defaultStretch: go.GraphObject.None
                },
                $("ContextMenuButton",
                    $(go.TextBlock, "Ungroup", {
                        width: 100,
                        height: 25,
                        background: '#004780',
                        stroke: '#fff',
                        textAlign: 'center',
                        verticalAlignment: go.Spot.Center,
                        margin: 0
                    }), {
                        mouseOver: function(e, obj) {
                            var toolTipDIV = document.getElementById('groupsubheadermenu');
                            var pt = e.diagram.lastInput.viewPoint;
                            jQuery('#groupsubheadermenu').html('< Ctrl + Shift + G >');
                            toolTipDIV.style.left = (pt.x + 20) + "px";
                            toolTipDIV.style.top = (pt.y) + "px";
                        }
                    }, {
                        mouseLeave: function(e, obj) {
                            var toolTipDIV = document.getElementById('groupsubheadermenu');
                            toolTipDIV.style.left = -100 + "px";
                            toolTipDIV.style.top = -100 + "px";
                        }
                    }, {
                        click: function(e, obj) {
                            Ungroup();
                        }
                    }))
        }, {
            mouseEnter: function(e, obj, prev) {
                myDiagram.toolManager.hideToolTip()
            },
            click: function(e, obj) {
                myDiagram.toolManager.hideToolTip()
                var node = obj.part;
                myToolTip(node);
            },
            mouseHover: function(e, obj) {
                var node = obj.part;
                if (obj.part.data.__gohashid < 6000) {
                    jQuery('#myPaletteDiv' + obj.part.data.key).show();
                }
            },
            mouseLeave: function(e, obj) {
                hidemyToolTip('myPaletteDiv' + obj.part.data.key);
                myDiagram.toolManager.hideToolTip()
            },
            // mouseDrop: dropOntoNode
        },
    ),
); // end Group and call to add to template Map

How to fix this?

Take out the Placeholder from the Group.
https://gojs.net/latest/intro/sizedGroups.html

We add Placeholder for SubGraphExpanderButton.
Can we not include SubGraphExpanderButton in group, where we need group rotation?

Yes, you can have a $("SubGraphExpanderButton", . . .) in a Group without a Placeholder. You may need to add some Bindings such as:

  new go.Binding("visible", "isSubGraphExpanded").ofObject()

on whatever might have been surrounding your old Placeholder.