gojs 嵌套的 setDataProperty

gojs nested setDataProperty

最初我的节点数据看起来像这样:

{
  key: uuid,
  loc: "x y",
  color: color,
  param1: val1,
  param...:val...,
  paramn: valn
}

我决定将我的 gojs 详细信息和节点数据拆分为:

{
  meta: {
    key: uuid,
    loc: "x y",
    color: color
  }.
  data: {
    param1: val1,
    param...:val...,
    paramn: valn
  }
}

但放弃了将密钥移出,因为它看起来需要在 root 中并解决了这个问题:

{
  key: uuid,
  meta: {
    loc: "x y",
    color: color
  }.
  data: {
    param1: val1,
    param...:val...,
    paramn: valn
  }
}

我用这样的东西更新了简单的单向绑定:

// old way
new go.Binding('fill', 'color')

// new way
new go.Binding('fill', 'meta', meta => meta.color)

对于双向绑定,我在采用 fromLocation 函数时遇到了一些问题,如下所示:

// 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)

我不清楚我是否需​​要对位置进行字符串化,所以我没有;但因为我保存了一些遗留图表,所以我暂时仍在处理它

// 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;
};

我在 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) });

};

当我查看 lodash 克隆时,元数据已填充,但此步骤的执行方式是将 meta 道具设置为 undefined,但它看起来不像任何东西我的其他代码在这个设定点之后修改它。


我采用了这里的代码: https://gojs.net/extras/bindingSubProperties.html

如下:

    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;
    };

他们的例子被字符串化了,所以我用它并调用如下:

makeTwoWaySubBinding('meta', 'location', 'loc', go.Point.parse, go.Point.stringify)

不过我遇到了同样的问题

const makeLocationTwoWayBind = () => {

  const locationTwoWayBind = new go.Binding('location', 'meta');
  locationTwoWayBind.mode = go.Binding.TwoWay;
  locationTwoWayBind.converter = (meta, targetObj) => {
    // gets the location from the node data
    const loc = go.Point.parse(meta.loc);
    return loc;
  };
  locationTwoWayBind.backConverter = (loc, nodeData, model) => {
    // updates the location on the nodeData
    const meta = Object.assign(_.cloneDeep(nodeData.meta), { loc: go.Point.stringify(loc) });
    return meta;
  };

  return locationTwoWayBind;
};

所以部分问题是我仍在使用 loc 另外,我不确定为什么示例代码使用模型方法 setDataProperty 看起来转换器执行类似的行为就像简单的 returns


小吐槽

The `converter` and `backConverter` were -- IMO -- counterintuitively named.
The converter takes the data from the model and applies to to the diagram,
the back converter saves data to the model

that became clear after looking at the input params,
but gave me pause a number of times

the model function names `toLocation` and `fromLocation`
don't really help
I would consider using something like marshall and unmarshall instead.

marshall = backConverter = fromLocation
unmarshall = converter = toLocatation

无论如何; converter 只需 return the parsed location 就足够了,backConverter 需要 return meta 因为 meta 是 [=20= 中指定的键] 构造函数。我在 backConverter 中更新了 metaloc 参数,然后 return 更新了 meta

现在我找到了我要找的东西:

{
  key: uuid,
  meta: {
    loc: "x y", <--- locationTwoWayBind handles this
    color: color
  }.
  data: {
    param1: val1,
    param...:val...,
    paramn: valn
  }
}