Get the selected item Array Data and Save

Hi,
Angular Selectable fields is verified and applied in my codes. Thanks. And selection is able to retrieve the itemArray record while isSelectedField(), setSelectableFileds() and onFieldClick() methods are part of InitDiagram method.

From above class level - assigned property of selected Item Array (this.taskID, this.addUser of selected device and user) is not accessible at ngAfterViewInit() or at saveUsers() methods. which is undefined. Below is the part of initDiagram() is able to retrieve the selected item Array data.

const UnselectedBrush = "lightgray";  // item appearance, if not "selected"
    // const SelectedBrush = "cyan";   // item appearance, if "selected"

    // const isFieldSelected = (item) => { return item.background !== UnselectedBrush; };

    // const setFieldSelected = (item, sel) => {
    //   if (sel) {
    //     item.background = SelectedBrush;
    //     console.log(item.data.name)
    //     if (!item.data.id) {
    //       this.addUser = item.data.name
    //       console.log(this.addUser)
    //       console.log("addUser = " + this.addUser)
    //     } else {
    //       this.taskID = item.data.id
    //       console.log("taskID == " + this.taskID)
    //     }
    //   } else {
    //     item.background = UnselectedBrush;
    //   }
    // }

Next as per your update, added two way bindings and brought the isSelectedField(), setSelectableFileds() and onFieldClick() methods as instance methods of the diagram component.
Am getting TypeError C is not a function due to click event - this.onFieldClick().

Now, from Selectable Fields example trying to apply the findAllSelectedItems method in my Input Event (“ObjectSingleClicked”) approach as below

Kindly request your help to get and save the selected Item Array.

public state: AppState = {
    // Diagram state props  
    fixedConfNodeData: [
      { key: "Devices List" },
      { key: "Users List" }
    ],
    skipsDiagramUpdate: false,
  };

public initDiagram(): go.Diagram {
    const $ = go.GraphObject.make
    console.log("Inside init CALL-DIAGRAM >>>")
    const callDia = $(go.Diagram, {
      "undoManager.isEnabled": true,
      validCycle: go.Diagram.CycleNotDirected,  // don't allow loops    

      layout:
        $(go.GridLayout, { sorting: go.GridLayout.Forward }), // use a GridLayout

      model: new go.GraphLinksModel(
        {
          copiesArrays: true,
          copiesArrayObjects: true,
          linkFromPortIdProperty: "fromPort",
          linkToPortIdProperty: "toPort",
          nodeKeyProperty: 'key',
          linkKeyProperty: 'key', // IMPORTANT! must be defined for merges and data sync when using GraphLinksModel
          // positive keys for nodes
          makeUniqueKeyFunction: (m: go.Model, data: any) => {
            let k = data.key || 1;
            while (m.findNodeDataForKey(k)) k++;
            data.key = k;
            return k;
          },
          // negative keys for links
          makeUniqueLinkKeyFunction: (m: go.GraphLinksModel, data: any) => {
            let k = data.key || -1;
            while (m.findLinkDataForKey(k)) k--;
            data.key = k;
            return k;
          },
        }
      ),
    }
    );
 const onFieldClick = (e, item) => {
      let oldskips = item.diagram.skipsUndoManager;
      item.diagram.skipsUndoManager = true;
      if (e.control || e.meta) {
        this.setFieldSelected(item, !this.isFieldSelected(item));
        item.part.isSelected = item.panel.elements.any(this.isFieldSelected);
      } else if (e.shift) {
        // alternative policy: select all fields between this item and some other one??
        if (!this.isFieldSelected(item)) this.setFieldSelected(item, true);
        item.part.isSelected = true;
      } else {
        if (!this.isFieldSelected(item)) {
          // deselect all sibling items
          item.panel.elements.each(it => {
            if (it !== item) this.setFieldSelected(it, false);
          });
          this.setFieldSelected(item, true);
          console.log(item.data.id)
        }
        item.part.isSelected = true;
      }
      item.diagram.skipsUndoManager = oldskips;
    }

const fieldTemplate = $(go.Panel, "Auto",  // this Panel is a row in the containing Table
      new go.Binding("portId", "name").makeTwoWay(),  // this Panel is a "port"
      {
        background: "lightgray",
        alignment: go.Spot.Center,
      },    
      { click: onFieldClick }, // select items -- the background indicates "selected" when not UnselectedBrush


      $(go.Shape, "RoundedRectangle", roundedRectangleParams,
        {
          name: "SHAPE",
          fill: "transparent", 
          strokeWidth: 0,
          width: 160,
          height: 100,
          margin: 45,
          alignment: go.Spot.Center,
        },

      ),
      $(go.Panel, "Vertical",
        $(go.Panel, "Table",
          $(go.TextBlock,
            {
              row: 0, alignment: go.Spot.Center,
              font: "16pt Sego UI,sans-serif",
              stroke: "rgba(0, 0, 0, .87)",
              maxSize: new go.Size(150, NaN),
            },
            new go.Binding("text", "name").makeTwoWay()
          ),
        )
      )
    );

callDia.nodeTemplate = $(go.Node, "Auto",
      {
        alignment: go.Spot.Center,
        isShadowed: true, shadowBlur: 5,
        shadowOffset: new go.Point(1, 5),
        shadowColor: "rgba(0, 0, 0, 1)",
      },
      $(go.Shape, "RoundedRectangle",
        {
          fill: "transparent",//this.UnselectedBrush,
          stroke: "lightyellow",
          strokeWidth: 0.25,
          stretch: go.GraphObject.UniformToFill,  // as wide as the whole node
        },
        new go.Binding("fill", "isSelected", b => b ? this.SelectedBrush : this.UnselectedBrush).ofObject().makeTwoWay(),
        ),
      // the content consists of a header and a list of items
      $(go.Panel, "Vertical",// "Horizontal",       
        // this is the header for the whole node
        $(go.Panel, "Auto",
          {
            stretch: go.GraphObject.UniformToFill,
            isPanelMain: true
          },  // as wide as the whole node
          $(go.Shape,
            { fill: "cyan", stroke: null, height: 60 }), //"#1570A6"
          $(go.TextBlock,
            {
              alignment: go.Spot.Center,
              margin: 3,
              stroke: "black",
              textAlign: "center",
              font: "bold 16pt Sego UI,sans-serif",
              maxSize: new go.Size(150, NaN),
            },
            new go.Binding("text", "key").makeTwoWay())),

        // 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, "Horizontal",  // "Table",
          new go.Binding("itemArray", "fields"),
          {
            name: "TABLE",
            padding: 2,
            minSize: new go.Size(100, 15),
            defaultStretch: go.GraphObject.Horizontal,
            itemTemplate: fieldTemplate
          },
        )  // end Table Panel of items
      )  // end Vertical Panel
    );// END CallDia.NodeTemplate    
    return callDia;
  };

public fixedConfDiagram = null;
public ngAfterViewInit() {
    if (this.fixedConfDiagram) return;
    this.fixedConfDiagram = this.fixedConfComponent.diagram;    
    let fixConfDeviceKey = this.state.fixedConfNodeData[0].key;
    this.service.getRecords(this.fixedConference_url).subscribe((result) => {    
      this.confData = result;    
      this.updateFields(fixConfDeviceKey, result)
    });

    let usersKey = this.state.fixedConfNodeData[1].key
    this.service.getRecords(this.profileUsers_url).subscribe((result) => {      
      this.userData = result
      this.updateFields(usersKey, result)     
    });
 this.fixedConfDiagram.addDiagramListener("ObjectSingleClicked", (e) => {
      let part = e.subject.part.data.key
      // let selecteditems = [];
      if (part === "Devices List") {
        let items = e.subject.part.data.fields
        console.log(items)        
      }
      else console.log("false.. IT is USERS LIST")

      const items = [];
        for (const nit = this.fixedConfDiagram.nodes; nit.next();) {
          const node = nit.value;
          console.log(node.data)
          const table = node.findObject("TABLE");
          if (table) {
            for (const iit = table.elements; iit.next();) {
              const itempanel = iit.value;
              console.log(itempanel.data)
              if (this.isFieldSelected(itempanel)) items.push(itempanel);
            }
          }
        }
        console.log(items)
      console.log("LISTENER = addUser = " + this.addUser)
      console.log("LISTENER = taskID = " + this.taskID)
    });
  };

 saveMembers() {
    console.log("saveMembers is called")
    console.log(this.taskID)
    console.log(this.addUser)
};
  updateFields = (key, fieldsArray) => {
    const data = this.fixedConfDiagram.model.findNodeDataForKey(key);
    if (!data) return;
    this.fixedConfDiagram.model.commit(m => m.set(data, "fields", fieldsArray));
  };

 UnselectedBrush = "lightgray"; // item appearance, if not "selected"
  SelectedBrush = "cyan";   // item appearance, if "selected"

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

  setFieldSelected = (item, sel) => {
    if (sel) {
      item.background = this.SelectedBrush;
      console.log(item.panel.data.name)
    } else {
      item.background = this.UnselectedBrush;
    }
  };
}

I have read your code, but I am unable to debug it with the information that you have provided. I suggest using go-debug.js instead of go.js and stepping through the code carefully.

Am already using go-debug.js in my html… Request your help to update the angular-selectable fields example with findAllSelectedFIelds() will implement first in the standalone and then apply it to get the data…
Thanks

As I said, there isn’t enough information for me to attempt to debug your code. Which I’m not supposed to do, anyway.

Oops, Attached the remaining typescript code is here…

import { ChangeDetectorRef, Component, OnInit, TemplateRef, ViewChild, ViewEncapsulation } from '@angular/core';
import { PresentationService } from 'src/app/service/presentation.service';
import * as go from 'gojs';
import { DataSyncService, DiagramComponent } from 'gojs-angular';
import produce from "immer";
import { environment } from 'src/environments/environment';
import { CoreService } from 'src/app/service/core.service';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { MatDialog } from '@angular/material/dialog';
import { LoggerService } from 'src/app/service/logger.service';
import { AlertService } from 'src/app/service/alert.service';

interface AppState {
  fixedConfNodeData: Array<go.ObjectData>;
  // diagramNodeData: Array<go.ObjectData>;
  // diagramLinkData: Array<go.ObjectData>;
  skipsDiagramUpdate: boolean;
}

@Component({
  selector: 'app-resource-planning-view-diagram',
  templateUrl: './resource-planning-view-diagram.component.html',
  styleUrls: ['./resource-planning-view-diagram.component.css'],
  encapsulation: ViewEncapsulation.None,
})

export class ResourcePlanningViewDiagramComponent implements OnInit {
  
  @ViewChild("myFixedConf", { static: true }) public fixedConfComponent: DiagramComponent;
 
  @ViewChild('myInfoDialog') infoDialog = {} as TemplateRef<string>;
  dialogRef: any;
  myInfo = "";

  constructor(private cdr: ChangeDetectorRef, private service: CoreService, private http: HttpClient, private matDialog: MatDialog, private ps: PresentationService, private logger: LoggerService, private alertService: AlertService) { };

   public fixedConfDiagram = null;
   profile = this.ps.getRecord(this.ps.idx)
   newConfData;
  newName;
  confData;
  userData;
  presentNames = [];
  confId;
  tasks = [];
  newMembers = [];

  addUser;
  taskID;
  item: go.Node;

  id;
  user;

  public diagramDivClassName: string = "myDiagramDiv";
  fixedConference_url = environment.rpvUrl_gojs_lineconference_get
    .replace('{server_ip}', this.server_ip)
    .replace('{server_port}', environment.server_port)
    .replace('{profileId}', this.profileId)

  // public fixedConf_put_url = environment.rpvUrl_gojs_lineconference_putMembers //conference ID here
  //   .replace('{server_ip}', this.server_ip)
  //   .replace('{server_port}', environment.server_port)
  // .replace('{confId}', this.confId) //conference ID here
 ngOnInit(): void { }

And the HTML is as below

 <script src="go-debug.js"></script>

<div class="left" style="width: 100%">

 <mat-tab label="Fixed Conference">
      <mat-card-actions style="text-align: right; margin-right: 40px;">
        <mat-dialog-actions align="end">
          <button id="showDialog" (click)="addFixedConf()" mat-raised-button>NEW</button>
        </mat-dialog-actions>
      </mat-card-actions>
      <gojs-diagram #myFixedConf [initDiagram]="initDiagram" [divClassName]="diagramDivClassName"
        [nodeDataArray]="state.fixedConfNodeData" (modelChange)="diagramModelChange($event)"
        [(skipsDiagramUpdate)]="state.skipsDiagramUpdate">
      </gojs-diagram>
    </mat-tab>
</div>
  <div class="btn-text-right">
    <button (click)="back()">Back</button>
    <button (click)="saveMembers()">Save</button>
  </div>

Thanks

You still haven’t provided the stack trace and relevant state data so that we could have any hope to guess what might be happening.

Again, I recomend that you debug this by stepping through the code and checking the state of everything.

Hmmm, although it should not be the cause of an error, I would think that you should be collecting references to data objects, not references to Panels.

Yes, am trying to debug step by step and thank you again your help… And for your info I can’t share the real time data as an employee… some data in the object are removed here for sharing purpose. And also the data is received through CRUD operations for the whole Project… Hence sharing is not effective as well in this aspect.

I have updated in the previous post that stackbiltz selectable fields sample is working fine and managed to execute it… And today applied it with few sample data as shared here… And again the same type error c is not a function popped up…

“references to data objects” means referring to node.findObject(“TABLE”) right.
but am getting the console output as panel#Auto object… which is not clear and confusing…

But while the onFieldClick() method is brought out of the class component… and the method works fine… but still not able to retrieve the selected data…As the

setFieldSelected(item, true);

in the above method causes some issues and trying to overcome it.

import { Component, ViewChild, ViewEncapsulation } from '@angular/core';
import * as go from 'gojs';
import { DataSyncService, DiagramComponent } from 'gojs-angular';
import produce from 'immer';

interface AppState {
  diagramNodeData: Array<go.ObjectData>;
  // diagramLinkData: Array<go.ObjectData>;
  skipsDiagramUpdate: boolean;
}

@Component({
  selector: 'app-selectable-fields',
  templateUrl: './selectable-fields.component.html',
  styleUrls: ['./selectable-fields.component.css'],
  encapsulation: ViewEncapsulation.ShadowDom
})

export class SelectableFieldsComponent {
  @ViewChild("myDiagram", { static: true })
  public myDiagramComponent: DiagramComponent;
  constructor() { }
  public mydiagram: go.Diagram = null;
  public diagramDivClassName: string = "myDiagramDiv";
  UnselectedBrush = "transparent";  // item appearance, if not "selected"
  SelectedBrush = "dodgerblue";   // item appearance, if "selected"

  public state: AppState = {
    // diagramModelData: { prop: "value" },
    skipsDiagramUpdate: false,

    diagramNodeData: [
      {
        key: "Devices List",
        fields: [
          {
            "id": 1,
            "maxMember": 120,
            "profileID": 1,
            "dateCreated": "2023-04-06T15:35:16.000+08:00",
            "dateUpdated": "2023-10-30T15:07:07.000+08:00",
            "name": "Conf_1"
          },
          {
            "id": 2,
            "maxMember": 120,
            "profileID": 1,
            "dateCreated": "2023-04-06T15:35:16.000+08:00",
            "dateUpdated": "2023-10-30T15:07:07.000+08:00",
            "name": "Conf_2"
          },
        ]
      },
      {
        key: "Users List",
        fields: [
          {
            "name": "S6_U2",
            "type": "USER",
            "profileID": 1
          },
          {
            "name": "S6_U3",
            "type": "USER",
            "profileID": 1,
          },
        ]
      }

      // {
      //   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: "10 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: "70 0"
      // }
    ]
  }

  public initDiagram(): go.Diagram {
    const $ = go.GraphObject.make;

    const dia = $(go.Diagram, {

      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) this.showModel();
      // },
      'clickCreatingTool.archetypeNodeData': {
        text: 'new node',
        color: 'lightblue',
      },
      "undoManager.isEnabled": true,

      model: $(go.GraphLinksModel, {
        copiesArrays: true,
        copiesArrayObjects: true,
        linkFromPortIdProperty: 'fromPort',
        linkToPortIdProperty: 'toPort',
        linkKeyProperty: 'key', // IMPORTANT! must be defined for merges and data
        // positive keys for nodes
        makeUniqueKeyFunction: (m: go.Model, data: any) => {
          let k = data.key || 1;
          while (m.findNodeDataForKey(k)) k++;
          data.key = k;
          return k;
        },
        // negative keys for links
        makeUniqueLinkKeyFunction: (m: go.GraphLinksModel, data: any) => {
          let k = data.key || -1;
          while (m.findLinkDataForKey(k)) k--;
          data.key = k;
          return k;
        },

        nodeKeyProperty: "key"

      }),

    });

    // 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.
    const fieldTemplate =
      $(go.Panel, "TableRow",  // this Panel is a row in the containing Table
        new go.Binding("portId", "name"),  // this Panel is a "port"
        {
          background: "lightgray", //this.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: this.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".
    dia.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").makeTwoWay())),
          // 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").makeTwoWay()
          )  // end Table Panel of items
        )  // end Vertical Panel
      );  // end Node

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

    return dia;
  }

  // When the diagram model changes, update app data to reflect those changes
  public diagramModelChange(changes: go.IncrementalData) {
    if (!changes) return;
    const appComp = this;
    this.state = produce(this.state, (draft) => {
      draft.skipsDiagramUpdate = true;
      draft.diagramNodeData = DataSyncService.syncNodeData(
        changes,
        draft.diagramNodeData,
        appComp.mydiagram.model
      );
      // draft.diagramLinkData = DataSyncService.syncLinkData(
      //   changes,
      //   draft.diagramLinkData,
      //   appComp.mydiagram.model as go.GraphLinksModel
      // );
      draft.skipsDiagramUpdate = true; // the GoJS model already knows about these updates
    });
  }


  public ngAfterViewInit() {
    if (this.mydiagram) return;
    this.mydiagram = this.myDiagramComponent.diagram;
    // this.showModel(); 

    const rvdComp: SelectableFieldsComponent = this;

  }

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

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

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

  // showModel() {
  //   // throw new Error('Function not implemented.');
  // document.getElementById("mySavedModel").textContent = this.diagram.model.toJson();
  // }

  // this is a bit inefficient, but should be OK for normal-sized graphs with reasonable numbers of items per node
  // findAllSelectedItems() {
  //   var items = [];
  //   for (const nit = this.mydiagram.nodes; nit.next();) {
  //     var node = nit.value;
  //     var table = node.findObject("TABLE");
  //     if (table) {
  //       for (var iit = table.panel.elements; iit.next();) {
  //         var itempanel = iit.value;
  //         if (this.isFieldSelected(itempanel)) items.push(itempanel);
  //       }
  //     }
  //   }    
  //   return items;
  // }
}
##############HTML###################
<p>selectable-fields works!</p>
<!-- Diagram id='recordingDiagramDiv -->
<script src="go-debug.js"></script>
<div 
style=" flex-grow: 1; 
    width: 95%;
    height: 450px;
    border: solid 1px #1a252f;
    position: relative;
    -webkit-tap-highlight-color: rgba(255, 255, 255, 0);
  ">
    <gojs-diagram #myDiagram [initDiagram]="initDiagram" [nodeDataArray]="state.diagramNodeData"
        [divClassName]="diagramDivClassName" [(skipsDiagramUpdate)]="state.skipsDiagramUpdate" (modelChange)="diagramModelChange($event)">
    </gojs-diagram>
</div>
<!-- <textarea id="mySavedModel" style="width:100%;height:300px"></textarea> -->

Stack trace is here as below:
ERROR TypeError: c is not a function at we (go-module.js:288:104) at push.1963.ue.standardMouseClick (go-module.js:286:382) at push.1963.tg.doMouseUp (go-module.js:468:84) at push.1963.R.doMouseUp (go-module.js:599:279) at a.pk (go-module.js:815:495) at ZoneDelegate.invokeTask (zone.js:434:35) at Object.onInvokeTask (core.mjs:26339:33) at ZoneDelegate.invokeTask (zone.js:433:64) at Zone.runTask (zone.js:205:51) at ZoneTask.invokeTask [as invoke] (zone.js:516:38)

handleError @ core.mjs:7626
next @ core.mjs:27040
next @ Subscriber.js:91
_next @ Subscriber.js:60
next @ Subscriber.js:31
(anonymous) @ Subject.js:34
errorContext @ errorContext.js:19
next @ Subject.js:27
emit @ core.mjs:22871
(anonymous) @ core.mjs:26378
ZoneDelegate.invoke @ zone.js:400
Zone.run @ zone.js:160
runOutsideAngular @ core.mjs:26251
onHandleError @ core.mjs:26378
ZoneDelegate.handleError @ zone.js:404
Zone.runTask @ zone.js:208
ZoneTask.invokeTask @ zone.js:516
invokeTask @ zone.js:1656
globalZoneAwareCallback @ zone.js:1682
Show less

Thanks

Make those methods and Brush members static. They don’t need to refer to this at all.

I expect the problem is that when you set the click function to this.onFieldClick, Angular doesn’t have this bound, so it can’t call the function properly.

I’ve updated the StackBlitz with static methods instead of functions in initDiagram. gojs-angular-selectable-fields - StackBlitz

Thanks for the stack trace.

I suspect that the problem is that you are using a method as the GraphObject.click property value that must be an event handler function (or null). When that method is called as a regular function it doesn’t have a binding for this.

Try something like:

  click: this.onFieldClick.bind(this)

Or else change your definition of onFieldClick not to depend on this.

Thanks a lot Walter and Jhardy. Able to save it now and really appreciate your guidance and help… As am not a pure tech guy am bit struggling, experience matters and will work continuously to gain it.