javascriptangulartypescriptjointjs

JointJS Adding a Port to a custom element


I created a custom element using the jointjs tutorial like this:


CustomRect = joint.dia.Element.define('example.CustomRect', {
  attrs: {
    rect: {
      refX: 0,
      refY: 0,
      refWidth: '116',
      refHeight: '70',
      strokeWidth: 1,
      stroke: '#000000',
      fill: '#FFFFFF'
    },
    label: {
      textAnchor: 'left',
      refX: 10,
      fill: 'black',
      fontSize: 18,
      text: 'text'
    },
    upperRect: {
      strokeWidth: 1,
      stroke: '#000000',
      fill: 'rgba(255,0,0,0.3)',
      cursor: 'pointer'
    }
  }
}, {
    markup: [{
      tagName: 'rect',
      selector: 'rect'
    },
    {
      tagName: 'text',
      selector: 'label'
    },
    {
      tagName: 'rect',
      selector: 'upperRect'
    }]
})

...

let customRect = new this.CustomRect()

customRect.attr({
  upperRect: {
    refWidth: '116',
    refHeight: '10',
    refX: 0,
    refY: -11,
    event: 'element:upperRect:pointerdown'
  }
})

Furthermore, I tried adding Ports with the Port API for joint.dia.Element like this:

customRect.addPorts([
  {
    args: {
      y: 30
    },
    z: 0
  }
]);

This does add Ports to my element, but they don't have the functionality they should have, so they're just some circles that do nothing.

The method shown in the Port Tutorial does not work, since I'm not using joint.shapes.devs.Model for my custom element, because then I can't customize it like the joint.dia.Element element (or at least I think I can't).

So, how can I add Ports to a custom element defined with joint.dia.Element that have the functionality they should have (as shown in the Port Tutorial)?


Solution

  • Unfortunately, the documentation does not explain this clear enough. If you want to make the ports interactive you need to set the magnet attribute on them.

    const CustomRect = joint.dia.Element.define('example.CustomRect', {
      /* ... */
      attrs: {
        root: {
          // Don't allow the root of the element to be target of a connection
          magnet: false
        }
      },
      ports: {
        items: [{
          id: 'port1',
          attrs: {
            portBody: {
              // The port can be a target of a connection
              // The user can create a link from the port by dragging the port
              magnet: true
            }
          }
        }, {
          id: 'port2',
          attrs: {
            portBody: {
              // The port can only become a target of a connection
              // The logic can be modified via paper.options.validateMagnet()
              magnet: 'passive'
            }
          }
        }]
      }
    }, {
      /* ... */
      portMarkup: [{
        tagName: 'circle',
        selector: 'portBody',
        attributes: {
          'r': 10,
          'fill': '#FFFFFF',
          'stroke': '#000000'
          // If all the magnets are `true` / `passive` feel free to define
          // the magnet here in the default port markup or per a port group
          // 'magnet': true
        }
      }]
    });