clientIO / joint

A proven SVG-based JavaScript diagramming library powering exceptional UIs

Home Page:https://jointjs.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[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 in CBase
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!