[Bug]: Multiple inheritance with custom shapes not working (as expected?)
alexandernst opened this issue · comments
What happened?
I'm playing with the examples at https://resources.jointjs.com/tutorial/ts-shape and I figured out I'd try to create a Base
shape that extends from dia.Link
, which then I'd use to create MyLink
. It turns out this doesn't work.
I'm not really sure why (maybe it has something to do with the way defaults
is being called?).
Demo: https://codesandbox.io/s/joint-custom-link-extend-playground-ngs9zn
Note that
class CLink extends CBase { // <--- doesn't render the link
class CLink extends joint.shapes.standard.Link { // <--- renders the link
Version
3.7.5
What browsers are you seeing the problem on?
Firefox, Chrome, Safari
What operating system are you seeing the problem on?
Mac
It is the defaults
:)
- wrong order of
merge
arguments super.default
is a function inCBase
class CLink extends CBase {
defaults() {
return joint.util.merge(
{},
super.defaults(),
{
type: "CLink",
attrs: {
line: {
stroke: "#ccc",
strokeWidth: 2
}
}
},
);
}
}
Ooohh! 🤔
Ok, I have another questions. Why CBase
is merging super.defaults
, but CLink
is merging super.defaults()
? What is the difference between using super.defaults
as a value and calling super.defaults()
as a function?
The shapes.standard.Link class is defined via the define method which using the extend method of Backbone. If you create a Backbone.Model
this way (ES5 way), the defaults
is a property, not a method. Therefore CBase
needs to access it as a property.
The ES Class CBase
defines the defaults
as a method. Therefore CLink
has to call it as a function.
I recommend reading this article which should explain this in detail. Also reading this Backbone issue might be helpful.
Oohh, now I get it. Good thing to know :)
Thank you!!
I have an extra question 🙏
Would it be possible to extend from 2 classes using this method? Lets say that I have CBaseLinkA
which defines the stroke
color (using the defaults()
) and CBaseLinkB
which defines the strokeWidth
(also using the defaults()
) and the markup
attribute. Would it be possible to do something like
class MyLink extends merge(CBaseLinkA, CBaseLinkB) {
defaults() {
return joint.util.merge(
{
attrs: { line: { fill: "red" } }
},
super.defaults() // ????
)
}
}
Perhaps you can check this discussion.
Hmmm, I think I saw similar stuff in SO, but I'm not really sure how to handle the defaults()
, since that is threated in a very special way. I'll play around and report back if I find a way of achieving this!