Using GoJS with Angular

Examples of most of the topics discussed on this page can be found in the gojs-angular-basic(Needs different name???) project, which serves as a simple starter project.

If you are new to GoJS, it may be helpful to first visit the Getting Started Tutorial.

The easiest way to get a component set up for a GoJS Diagram is to use the gojs-angular package, which exports Angular Components for GoJS Diagrams, Palettes, and Overviews. The gojs-angular-basic(???) project demonstrates how to use these components. More information about the package, including the various props it takes, can be found on the Github or NPM pages. Our examples will be using a GraphLinksModel, but any model can be used.

You can see a sample project using all GoJS / Angular Components here.

Installation

To use the published components, make sure you install GoJS and gojs-angular: npm install gojs gojs-angular.

About Component Styling

Whether you are using the published Diagram, Palette, or Overview Angular / GoJS Components, you will probably want to style them. First, you'll need to style a CSS class for the div of your GoJS Diagram / Palette / Overview such as:

/* app.component.css */
.myDiagramDiv {
  background: whitesmoke;
  width: 800px;
  height: 300px;
  border: 1px solid black;
}

In order to style the GoJS Diagram / Palette / Overivew div, which will reside in the Angular / GoJS Component(s) you are using, make sure you set encapsulation: ViewEncapsulation.None in the @Component decorator of the component holding your Angular / GoJS Component(s). Without this, your styling will not effect the component divs. Read more about Angular view encapsulation here.

Your @Component decorator for the component holding the your GoJS / Angular Component(s) should look something like:

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  encapsulation: ViewEncapsulation.None
})

Using the Diagram Component

Diagram Component accepts several @Input() Angular properties, some of which are optional. They are:

When you're done defining these properties, they might look something like this:

public initDiagram(): go.Diagram {

  const $ = go.GraphObject.make;
  const dia = $(go.Diagram, { 'undoManager.isEnabled': true });

  // define the Node template
  dia.nodeTemplate =
    $(go.Node, 'Auto',
      {
        toLinkable: true, fromLinkable: true
      },
      $(go.Shape, 'RoundedRectangle', { stroke: null },
        new go.Binding('fill', 'color')
      ),
      $(go.TextBlock, { margin: 8 },
        new go.Binding('text', 'key'))
    );

  return dia;
}

public diagramModel: go.GraphLinksModel = new go.GraphLinksModel([
  { key: 'Alpha', color: 'lightblue' },
  { key: 'Beta', color: 'orange' },
  { key: 'Gamma', color: 'lightgreen' },
  { key: 'Delta', color: 'pink' }
], [
    { key: -1, from: 'Alpha', to: 'Beta' },
    { key: -2, from: 'Alpha', to: 'Gamma' },
    { key: -3, from: 'Beta', to: 'Beta' },
    { key: -4, from: 'Gamma', to: 'Delta' },
    { key: -5, from: 'Delta', to: 'Alpha' }
  ]
);
public diagramDivClassName: string = 'myDiagramDiv';

Then, simply pass these properties to your Diagram Component in your template, like this:

<gojs-diagram #myDiagram [initDiagram]='initDiagram' [model]='diagramModel' [divClassName]='divClassName'></gojs-diagram>

And that's it! You will now have a GoJS Diagram working in your Angular application.

Using the Palette Component

The Palette Component accepts the following Angular @Input() properties.

Define these properties in your component that will hold that Palette Component, such as:

public initPalette(): go.Palette {
  const $ = go.GraphObject.make;
  const palette = $(go.Palette);

  // define the Node template
  palette.nodeTemplate =
    $(go.Node, 'Auto',
      $(go.Shape, 'RoundedRectangle',
        {
          stroke: null
        },
        new go.Binding('fill', 'color')
      ),
      $(go.TextBlock, { margin: 8 },
        new go.Binding('text', 'key'))
    );

  palette.model = $(go.GraphLinksModel,
    {
      linkKeyProperty: 'key'  // IMPORTANT! must be defined for merges and data sync when using GraphLinksModel
    });

  return palette;
}
public paletteModel: go.GraphLinksModel = new go.GraphLinksModel([
  { key: 'Palette Node 1', color: 'firebrick' },
  { key: 'Palette Node 2', color: 'blueviolet' }
]);
public paletteDivClassName = 'myPaletteDiv';
      

Then pass these properties to your Palette Component in your template, like:

<gojs-palette #myPalette [initPalette]='initPalette' [model]='model' [divClassName]='pDivClassName'></nggojs-palette>

And that's it! You should now have a GoJS Palette Component working in your Angular application.

Using the Overview Component

The Overview Component accepts the following Angular @Input() properties.

Define these properties in the component that will hold your Overview Component, like:

public oDivClassName = 'myOverviewDiv';
public initOverview(): go.Overview {
  const $ = go.GraphObject.make;
  const overview = $(go.Overview);
  return overview;
}
public oModelData = { prop: 'val' };
public observedDiagram = null;
      

Then pass these properties to your Overview Component in your template, like:

<gojs-overview #myOverview [initOverview]='initOverview' [divClassName]='oDivClassName' [observedDiagram]='observedDiagram'></gojs-overview>

But wait! observedDiagram is null, so the Overview will not be observing anything! In order to assign your overview a Diagram to observe, you will have to reassign the observedDiagram property after initialization. To do so, simply reassign the bound observedDiagram property in your component holding your Overview Component in the ngAfterViewInit lifecycle hook.

Note that in order to avoid a ExpressionChangedAfterItHasBeenCheckedError, you must inform Angular to then detect changes. This can be done with the ChangeDetectorRef.detectChanges() method. You can inject a ChangeDetectorRef instance into your wrapper Component constructor, and use that after you alter observedDiagram to call detectChanges(). Like so:

constructor(private cdr: ChangeDetectorRef) { }

public ngAfterViewInit() {
  if (this.observedDiagram) return;
  // in this snippet, this.myDiagramComponent is a reference to a GoJS/Angular Diagram Component
  // that has a valid GoJS Diagram
  this.observedDiagram = this.myDiagramComponent.diagram;

  // IMPORTANT: without this, Angular will throw ExpressionChangedAfterItHasBeenCheckedError (dev mode only)
  this.cdr.detectChanges();
}
      

Now, after initialization, your overview should display appropriately.