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:
initDiagram
- A function that must return a GoJS Diagram. You may define your Diagram's Node and Link templates here.divClassName
- A class name for the div your Diagram will reside inmodel
- A valid GoJS Model for your Diagram. Whenever you change model data, be sure to use Model methods, likeset
oraddNodeData
so the data in your application updates along with the data in your Diagram
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.
initPalette
- A function that must return a GoJS Palette. You may define your Palette's Node and Link templates here.divClassName
- A class name for the div your Palette will reside inmodel
- A valid GoJS Model for your Palette. Whenever you change model data, be sure to use Model methods, likeset
oraddNodeData
so the data in your application updates along with the data in your Palette
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.
initOverview
- A function that must return a GoJS Overview.divClassName
- A class name for the div your Overview will reside inobservedDiagram
- The GoJS Diagram this Overview observes
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.