Skip to content

joint.util.cloneDeep(obj) corrupts Typescript objects #951

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
BoykoAlex opened this issue Sep 8, 2018 · 2 comments
Closed

joint.util.cloneDeep(obj) corrupts Typescript objects #951

BoykoAlex opened this issue Sep 8, 2018 · 2 comments

Comments

@BoykoAlex
Copy link

I happen to have a Typescript object with getters and setters set as one of the attribute on a Cell:
cell.attr(keyPath, tsObj)
A call to cell.removeAttr('someKeyPath') where someKeyPath doesn't involve the tsObj above corrupts the tsObj such that it becomes unusable all of a sudden. The culprit seems to be joint.util.cloneDeep(obj) that deep clones cell.attributes.attrs.
Is there anyway to leave TS objects (with prototype chain) untouched by deep clone? Treat them as other mutable types such as number and string?
This is a common problem it seems. For example this: angular/angular.js#5085

That was working in 1.X versions i think.

@kumilingus
Copy link
Contributor

Hi Alex,

you can try to override joint.util.deepClone with _.cloneDeepWith (https://lodash.com/docs/#cloneDeepWith) and use some customizer that takes your object into account. Or override the joint.dia.Cell.prototype.removeProp (https://github.com/clientIO/joint/blob/master/src/joint.dia.cell.js#L540) to use _.merge({}, this.get(property)).

To be on the same page, the attrs attribute suppose to store only the SVG presentation attributes. It's a hash, where keys are the selectors to an SVGElement and values are SVG attributes, which will be set to the SVGElement. Any other model-related data are meant to be stored outside the attrs object.

// a presentation attribute <text fontSize=16></text>
// element.attributes.attrs.label.fontSize
element.attr('label/fontSize', 16);
// a custom data
// element.attributes.myData
element.prop('myData', { test: true });
// WRONG
// <text my-data="[object Object]></text>"
element.attr('label/myData', { test: true });

So unless your tsObj getters dynamically return presentation attributes, you can avoid this issue by storing your data outside the attrs object.

Not, the cloning is necessary so the Backbone triggers a change event. In this case of removeProp() though, a simple shallow copy should also does the trick (I think).

@BoykoAlex
Copy link
Author

@kumilingus thank you! Should have thought about overriding joint.util.deepClone myself :-) I'll find time to move out properties from attrs outside of it somewhere. Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants