Originally my node data looked something like this:
{
key: uuid,
loc: "x y",
color: color,
param1: val1,
param...:val...,
paramn: valn
}
I decided I wanted to split my gojs details and node data into this:
{
meta: {
key: uuid,
loc: "x y",
color: color
}.
data: {
param1: val1,
param...:val...,
paramn: valn
}
}
but gave up on moving the key out since it looks like that needs to be in root and settled on this:
{
key: uuid,
meta: {
loc: "x y",
color: color
}.
data: {
param1: val1,
param...:val...,
paramn: valn
}
}
I updated the simple one-way binding with stuff like this:
// old way
new go.Binding('fill', 'color')
// new way
new go.Binding('fill', 'meta', meta => meta.color)
For the two-way binding I hit some snags adopting the fromLocation function as follows:
// This worked fine with a flat state:
// new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
// I decided to move my stat into a sub object called meta with the following:
new go.Binding('location', 'meta', toLocation).makeTwoWay(fromLocation)
It wasn't clear to me that I needed to stringify the location, so I'm not; but because I have some legacy diagrams saved I'm still handling that for the time being
// This works just fine
const toLocation = (meta, node) => {
// pulls the loc out of the meta, and parses into go.point
let output = meta.loc;
// TODO: Shouldn't need to check for a string since we're storing raw values now
if (typeof output === 'string') {
output = go.Point.parse(output);
}
console.log('toLocation:', { output, meta });
return output;
};
I get really odd behavior in the fromLocation:
const fromLocation = (loc, data, model) => {
// writes the loc as a string to the meta prop
console.log('fromLocation IN:', { data: _.cloneDeep(data) });
const meta = _.cloneDeep(data.meta);
meta.loc = loc;
console.log('model.nodeDataArray:', model.nodeDataArray);
if (typeof data.meta !== 'undefined') {
console.log('fromLocation has meta:', { meta: data.meta, loc });
}
this.diagramReferenceService.startTransaction('updating meta');
model.setDataProperty(data, 'meta', meta);
data.meta = meta;
this.diagramReferenceService.commitTransaction('updating meta');
console.log('fromLocation OUT:', { data: _.cloneDeep(data) });
};
when I look at the lodash clone the meta is populated, but something about the way this step is executing is setting the meta
props to undefined
, but it doesn't look like any of my other code is modifying it after this set point.
I adopted the code from here: https://gojs.net/extras/bindingSubProperties.html
as follows:
const makeTwoWaySubBinding = (rootkey, targetname, sourcename, conversion, backconversion) => {
console.log('makeTwoWaySubBinding:', { rootkey, targetname, sourcename, conversion, backconversion })
const bind = new go.Binding(targetname, rootkey);
bind.mode = go.Binding.TwoWay;
bind.converter = (root, target) => {
const value = root[sourcename];
if (value === undefined) {
return target[targetname];
}
return (typeof conversion === 'function') ? conversion(value, target) : value;
};
bind.backConverter = (value, data, model) => {
const root = data[rootkey];
if (model) {
if (typeof backconversion === 'function') {
model.setDataProperty(root, sourcename, backconversion(value, root, model));
} else {
model.setDataProperty(root, sourcename, value);
}
} else {
root[sourcename] = (typeof backconversion === 'function') ? backconversion(value, root, model) : value;
return root;
}
};
return bind;
};
their example stringified, so I went with it and invoked as follows:
makeTwoWaySubBinding('meta', 'location', 'loc', go.Point.parse, go.Point.stringify)
I'm having the same issue though
So the issue was in part that I was still using
loc
Also, I'm not sure why the example code uses the model methodsetDataProperty
it seems like the converters perform similar behaviors as simple returnssmall rant
anyway; having the
converter
simplyreturn the parsed location
was sufficient, thebackConverter
needed to returnmeta
sincemeta
was the key specified in thego.Binding
constructor. I handled updating theloc
param ofmeta
in thebackConverter
then returned the updatedmeta
so now I have what I was looking for: