Using Dynamic Business Data as Label Text

Tips & Tricks

Summary

Rendering business data in a custom label style instead of the label text.
For a better user experience, please go to the integrated documentation viewer to read this article.

Description

A custom label style lets you easily use business data, for example, from the label tag as text, instead of the value of label.text. This makes it possible to let the graph render dynamically changing data without having to update the respective label items.

Style Implementation

For general advice on label style implementation, please follow the Custom Styles Tutorial.

To render data from the label tag, use the corresponding data in createVisual and updateVisual. For example, if you have an object with a name property stored in the label tag, your code could look like this:

createVisual(context) {
  const textElement = window.document.createElementNS("http://www.w3.org/2000/svg", "text");
  textElement.textContent = this.label.tag ? this.label.tag.name : "Empty Label";
  return new SvgVisual(textElement);
}

You might also have to adjust the getPreferredSize method to use the text from the business data instead of the label text for label measurement.

Adjusting Interactive Label Editing

To adjust label editing so that it modifies the business data instead of the label text, you need a custom IEditLabelHelper implementation.

This implementation gets and sets the business data from label.tag.name. Please modify $getLabelText and $setLabelText to work with your own business data model.
class MyEditLabelHelper extends EditLabelHelper {

  onLabelEditing(evt) {
    if (evt.owner === null || evt.owner.labels.count === 0) {
      return;
    }

    let listener = null;
    let canceledListener = null;

    const label = evt.owner.labels.first();

    const labelText = MyEditLabelHelper.$getLabelText(label);
    // create a dummy label
    const dummyLabel = new SimpleLabel(label.owner, labelText, label.layoutParameter);
    dummyLabel.preferredSize = label.preferredSize;
    dummyLabel.style = label.style;
    const editorMode = evt.context.canvasComponent.inputMode;
    if (editorMode && editorMode instanceof GraphEditorInputMode) {
      listener = (evt) => {
        // write edited label back to label tag
        const newText = evt.item.text;
        MyEditLabelHelper.$setLabelText(label, newText);
        // adjust the label size
        evt.context.canvasComponent.graph.adjustLabelPreferredSize(label);
        // deregister listeners
        editorMode.removeEventListener("label-text-changed", listener);
        editorMode.removeEventListener("label-text-editing-canceled", canceledListener);
      };
      canceledListener = (evt) => {
        // deregister listeners
        editorMode.removeEventListener("label-text-changed", listener);
        editorMode.removeEventListener("label-text-editing-canceled", canceledListener);
      };
      setTimeout(function() {
        // start editing
        editorMode.startLabelEditing(dummyLabel);
        editorMode.addEventListener("label-text-changed", listener);
        editorMode.addEventListener("label-text-editing-canceled", canceledListener);
      }, 10);
    }
  }

  static $getLabelText(label) {
    // return desired business data here
    return label.tag.name;
  }

  static $setLabelText(label, text) {
    // modify business data here
    return label.tag.name = text;
  }
}

You can put this EditLabelHelper implementation in the label's lookup. One way to do this is by overriding lookup in a custom style.

lookup(label, type) {
  if (type === IEditLabelHelper) {
    return new MyEditLabelHelper();
  }
  return super.lookup(label, type);
}

Another option is to add the class to the lookup using GraphDecorator.

const decorator = graphComponent.graph.decorator;
decorator.labels.editLabelHelper.addConstant(new MyEditLabelHelper());

Categories this article belongs to:
yFiles for HTML
Applies to:
yFiles for HTML: 3.0, 3.1
Keywords:
IEditLabelHelper - EditLabelHelper - editLabel