GoJS ItemArray binding with converter does not show textblock value

I am trying to display array inflormatino in a panel.
the code is written in that way

let conditionTextBlock = new go.TextBlock(); let conditionPanel = new Panel(Panel.Vertical); conditionPanel.add(conditionTextBlock);
I have his code to draw text block in a shape

   let inputsArrayPanel = new go.Panel(go.Panel.Vertical);
   inputsArrayPanel.bind(new go.Binding("itemArray", "", converter))
   let textBlock = new go.TextBlock();
    textBlock.text="SOME_DATA";
   inputsArrayPanel.add(textBlock);
    
    converter = (data)=> {
        return data.InternalData.**filter**(d=>pridicat);
    };

the converter returns an array.
I have noticed that gojs is calling the converter twice,
in the seocnd time i could see that gojs adds __gohashid

Question what __gohashid is it use for?
Why do I have to use the same array? Can you think of any way I can avoid it?

then I have a problem, when doing this code the layout is drawn
but no items are displayed in the from the array. (I cannot see "SOME_DATA" anywere)

when I drag the shape the binding happens again and now everything is OK.

Due to constraints I’m forced to use a method rather then bind to a given array - I’d like to be bound to a result of a service instead of the persisted array.

Thanks.

“__gohashid” is an internal property that you should not touch.
GoJS depends on that property in order to distinguish different JavaScript objects.

You should be able to avoid using data binding if you want to, but it will be more programming for you to do to handle a lot of different situations.

Still, I am curious why you think you cannot use data binding.

In my example I am using data binding -
inputsArrayPanel.bind(new go.Binding("itemArray", "", converter))

The symptom is that the nodes are shown, but the text blocks are empty and do not show the text "SOME_DATA".
Instead, it remains empty until I drag and move when of the nodes around.

I suspect it has something to do with __gohashid being absent (or, being stale) whenever I look at the array coming in as an input for the binding method.

The second time around (after moving the node) when I debug, I can see the __gohashid that’s been added, and then the text is displayed as well.

I suspect that the reason is that the filter returns a new (filtered) array.

No, the problem is that when Panel.itemArray gets a new value, whether by setting it or via a Binding, it will replace all of the existing elements with new ones generated from the values in the Array. So of course whatever elements you had initialized the Panel wih, they would all be removed.

My issue is not that the items are removed, but rather that they are part of the array, yet are not displayed as part of the node when first initialized.
They are displayed when I drag the node though…


Do you make all your changes within a transaction?

The only time it’s not needed is when you construct a model and replace the Diagram.model property.

No I am doing this on the Conversion function,
I am not changing any data, I read data from my model, filter it and return it.

Now I did try to do this

converter (a,b)
{
  b.diagram.startTransaction("TRAN");
   let result = a.mydata.filter(...);
  b.diagram.commitTransaction("TRAN");
  return reuslt;
}

this code does not feel good to me.
and it does not work…
What am I doing wrong?

Conversions should not be conducting a transaction.

When and why is the conversion function being called in the first place? That is what should be conducting a transaction.

This conversion is done
in the first time when the setting the graphlinkmodel to the diagram. (in this case there is no need to make transactin)
in the second time when I move the node from one place to another (in this case I do not have control on the operation)

OK, so the problem is an initialization one.

What is its Panel.itemTemplate? If you do not set the itemTemplate, do you see something for each item, even if it isn’t what you really want?

Hello walter, I manged to create a small program that shows the problem.
note that if I remove

node.bind(new go.Binding(“location”, “persistentLocation”).makeTwoWay());
then the graph works ok
note that if I remove the filter and return the list unfiltered
then the graph works ok

note that this line
this.diagram.div = this.goDiagramElementRef.nativeElement;
is the way i bind the graph to my div (I am using angular 2)

    this.diagram = new go.Diagram();
    this.diagram.initialContentAlignment = go.Spot.Center;

    let node = new go.Node(go.Panel.Auto);
    let shape = new go.Shape();
    shape.figure = "LoopLimit";
    shape.fill = "Green";
    let panel = new go.Panel(go.Panel.Vertical);
    let textBlock = new go.TextBlock();
    textBlock.bind(new go.Binding("text", "", (d)=> {
        return d.text;
    }));
    node.add(shape);
    node.add(panel);
    panel.bind(new go.Binding("itemArray", "", (myData)=> {
        let me = myData.list.filter((d)=>d.id != 2);
        console.log(me);
        return me;
    }));
    let conditionPanel = new go.Panel(go.Panel.Vertical);
    conditionPanel.add(textBlock);
    panel.itemTemplate = conditionPanel;

    this.diagram.nodeTemplate = node;


    node.bind(new go.Binding("location", "persistentLocation").makeTwoWay());

    this.diagram.div = this.goDiagramElementRef.nativeElement;
    let graphLinksModel = new go.GraphLinksModel();


    let myData = [
        {
            id: 1,
            list: [
                {id: 1, text: "AAA aaa"},
                {id: 1, text: "AAA aaaa"},
                {id: 2, text: "BBBB"}
            ]
        }
    ];
    graphLinksModel.nodeKeyProperty = "id";
    graphLinksModel.nodeDataArray = myData;
    this.diagram.model = graphLinksModel;

Is there a reason your Bindings aren’t defined in the following manners?

    textBlock.bind(new go.Binding("text"));
    panel.bind(new go.Binding("itemArray", "list", list => list.filter(d => d.id != 2)));

I’m not sure that will make a difference, but I thought I would ask before doing some experimentation.

(Also, if you don’t mind a comment – I think it’s easier to read code when there aren’t so many variable declarations. That’s why we provide the go.GraphObject.make static function.)

This seems to work for me. Note that there are no var or let variable declarations.

    const $ = go.GraphObject.make;

    this.diagram =
      $(go.Diagram, this.goDiagramElementRef.nativeElement,
        { initialContentAlignment: go.Spot.Center });

    this.diagram.nodeTemplate =
      $(go.Node, "Auto",
        new go.Binding("location", "persistentLocation").makeTwoWay(),
        $(go.Shape, "Cloud", { fill: "green" }),
        $(go.Panel, "Vertical",
          {
            margin: 6,
            itemTemplate:
              $(go.Panel,
                $(go.TextBlock, new go.Binding("text")))
          },
          new go.Binding("itemArray", "list", a => a.filter(d => d.id != 2))
        )
      );

    this.diagram.model =
      $(go.GraphLinksModel,
        {
          nodeKeyProperty: "id",
          nodeDataArray: [
            {
              id: 1, list: [
                { id: 1, text: "AAA aaa" },
                { id: 1, text: "AAA aaaa" },
                { id: 2, text: "BBBB" }
              ]
            },
            {
              id: 2, list: [
                { id: 3, text: "alpha" },
                { id: 2, text: "beta" },
                { id: 1, text: "gamma" }
              ]
            }
          ],
          linkDataArray: [
            { from: 1, to: 2 }
          ]
        });

However I have not tried this in Angular2. That should not matter, other than after there have been changes to the model you will need to update the diagram.