|
| 1 | +# gojs-angular |
| 2 | +Version 2.0 |
| 3 | +### By Northwoods Software for [GoJS 2.1](https://gojs.net) |
| 4 | + |
| 5 | +This project provides Angular components for [GoJS](https://gojs.net/latest/index.html) Diagrams, Palettes, and Overviews to simplify usage of GoJS within an Angular application. |
| 6 | +The implementation for these components is inside the projects/gojs-angular folder. |
| 7 | +See the [gojs-angular-basic project](https://github.com/NorthwoodsSoftware/gojs-angular-basic) for example usage and the |
| 8 | +[Intro page on using GoJS with Angular](https://gojs.net/latest/intro/angular.html) for more information. |
| 9 | + |
| 10 | +Version 2.0 expects immutability of all @Input properties to Diagram|Palette|Overview components, and removes `skipsPaletteUpdate` and `modelChange` properties from PaletteComponent. |
| 11 | + |
| 12 | +## Installation |
| 13 | + |
| 14 | +gojs-angular can be installed via NPM. This package has peer dependencies on GoJS and Angular, so make sure those are also installed or included on your page. |
| 15 | + |
| 16 | +### NPM |
| 17 | + |
| 18 | +```bash |
| 19 | +npm install --save gojs-angular |
| 20 | +``` |
| 21 | + |
| 22 | +## Making Changes |
| 23 | + |
| 24 | +If you want to change how the GoJS / Angular components are implemented, you will need to edit the files in `projects/gojs-angular`, then, from the main directory, run |
| 25 | + |
| 26 | +```bash |
| 27 | +npm run package |
| 28 | +``` |
| 29 | + |
| 30 | +which will create a new package in the folder, dist/angular-gojs, for you to use. Currently, gojs-angular depends on TypeScript and [immer](https://github.com/immerjs/immer). |
| 31 | + |
| 32 | +## Usage |
| 33 | + |
| 34 | +This package provides three components - DiagramComponent, PaletteComponent, and OverviewComponent - corresponding to the related GoJS classes. |
| 35 | + |
| 36 | +**Note**: As of version 2.0, `gojs-angular` assumes immutability of the `@Input` properties given to Diagram/Palette components. The [gojs-angular-basic repository](https://github.com/NorthwoodsSoftware/gojs-angular-basic) provides example usage of these components, as well as preserving state immutability (that project uses [immer](https://github.com/immerjs/immer) to maintain immutability, but you can use whatever you like best). |
| 37 | + |
| 38 | +Below is an example of how you might pass properties to each of the components provided by `gojs-angular`. Here, for immutable data properties that may change, they are stored in an object called `state`. This is not required, but helps with organization. |
| 39 | + |
| 40 | +```html |
| 41 | +<gojs-diagram |
| 42 | + [initDiagram]='initDiagram' |
| 43 | + [divClassName]='myDiagramDiv' |
| 44 | + [nodeDataArray]='state.diagramNodeDataArray' |
| 45 | + [linkDataArray]='state.diagramLinkDataArray' |
| 46 | + [modelData]='state.diagramModelData' |
| 47 | + (modelChange)='diagramModelChange($event)' |
| 48 | + [skipsDiagramUpdate]='state.skipsDiagramUpdate' |
| 49 | +></gojs-diagram> |
| 50 | + |
| 51 | +<gojs-palette |
| 52 | + [initPalette]='initPalette' |
| 53 | + [divClassName]='myPaletteDiv' |
| 54 | + [nodeDataArray]='state.paletteNodeData' |
| 55 | +></gojs-palette> |
| 56 | + |
| 57 | +<gojs-overview |
| 58 | + [initOverview]='initOverview' |
| 59 | + [divClassName]='myOverviewDiv' |
| 60 | + [observedDiagram]='observedDiagram' |
| 61 | +></gojs-overview> |
| 62 | +``` |
| 63 | + |
| 64 | +### Component Properties |
| 65 | + |
| 66 | +#### initDiagram/initPalette/initOverview |
| 67 | +Specifies a function that is reponsible for initializing and returning |
| 68 | +a GoJS Diagram, Palette, or Overview. In the case of an Overview, this |
| 69 | +is an optional property and when not provided, an Overview with default |
| 70 | +properties and centered content will be created. |
| 71 | + |
| 72 | +```js |
| 73 | +function initDiagram() { |
| 74 | + const $ = go.GraphObject.make; |
| 75 | + |
| 76 | + const diagram = $(go.Diagram, |
| 77 | + { |
| 78 | + 'undoManager.isEnabled': true, |
| 79 | + model: $(go.GraphLinksModel, { |
| 80 | + linkKeyProperty: 'key' // this should always be set when using a GraphLinksModel |
| 81 | + }) |
| 82 | + }); |
| 83 | + |
| 84 | + diagram.nodeTemplate = |
| 85 | + $(go.Node, 'Auto', // the Shape will go around the TextBlock |
| 86 | + $(go.Shape, 'RoundedRectangle', { strokeWidth: 0, fill: 'white' }, |
| 87 | + // Shape.fill is bound to Node.data.color |
| 88 | + new go.Binding('fill', 'color')), |
| 89 | + $(go.TextBlock, |
| 90 | + { margin: 8 }, // some room around the text |
| 91 | + // TextBlock.text is bound to Node.data.key |
| 92 | + new go.Binding('text', 'key')) |
| 93 | + ); |
| 94 | + |
| 95 | + return diagram; |
| 96 | +} |
| 97 | +``` |
| 98 | + |
| 99 | +#### divClassName |
| 100 | +Specifies the CSS classname to add to the rendered div. |
| 101 | +This should usually specify a width/height. |
| 102 | + |
| 103 | +```css |
| 104 | +.myDiagramDiv { |
| 105 | + width: 400px; |
| 106 | + height: 400px; |
| 107 | + border: 1px solid black; |
| 108 | +} |
| 109 | +``` |
| 110 | + |
| 111 | +#### nodeDataArray (DiagramComponent and PaletteComponent only) |
| 112 | +Specifies the array of nodes for the Diagram's model. |
| 113 | + |
| 114 | +```js |
| 115 | +nodeDataArray: [ |
| 116 | + { key: 'Alpha', color: 'lightblue' }, |
| 117 | + { key: 'Beta', color: 'orange' }, |
| 118 | + { key: 'Gamma', color: 'lightgreen' }, |
| 119 | + { key: 'Delta', color: 'pink' } |
| 120 | +] |
| 121 | +``` |
| 122 | + |
| 123 | +#### Optional - linkDataArray (DiagramComponent and PaletteComponent only) |
| 124 | + |
| 125 | +Specifies the array of links for the Diagram's model, only needed when using a [GraphLinksModel](https://gojs.net/latest/api/symbols/GraphLinksModel.html), not for Models or TreeModels. If are using this property, make sure to set the GraphLinksModel's linkKeyProperty in its corresponding initDiagram or initPalette function. |
| 126 | + |
| 127 | +```js |
| 128 | +linkDataArray: [ |
| 129 | + { key: -1, from: 'Alpha', to: 'Beta' }, |
| 130 | + { key: -2, from: 'Alpha', to: 'Gamma' }, |
| 131 | + { key: -3, from: 'Beta', to: 'Beta' }, |
| 132 | + { key: -4, from: 'Gamma', to: 'Delta' }, |
| 133 | + { key: -5, from: 'Delta', to: 'Alpha' } |
| 134 | +] |
| 135 | +``` |
| 136 | + |
| 137 | +#### Optional - modelData (DiagramComponent and PaletteComponent only) |
| 138 | +Specifies a shared modelData object for the Diagram's model. |
| 139 | + |
| 140 | +#### skipsDiagramUpdate (DiagramComponent only) |
| 141 | +Specifies whether the Diagram component should skip updating, often set to true when updating state from a GoJS model change. |
| 142 | + |
| 143 | +Because GoJS Palettes are read-only by default, this property is not present in PaletteComponent. |
| 144 | + |
| 145 | +#### modelChange (DiagramComponent) |
| 146 | +Specifies a function to be called when a GoJS transaction has completed. |
| 147 | +This function will typically be responsible for updating app-level state. Remember, these state properties are assumed to be immutable. This example `modelChange`, is taken from the [gojs-angular-basic](https://github.com/NorthwoodsSoftware/gojs-angular-basic) project, which uses [immer](https://github.com/immerjs/immer)'s `produce` function to maintain immutability. |
| 148 | + |
| 149 | +It is important that state updates made in this function include setting `skipsDiagramUpdate` to true, since the changes are known by GoJS. |
| 150 | + |
| 151 | +Because GoJS Palettes are read-only by default, this property is not present on PaletteComponent. Although there won't be user-driven changes to a Palette's model due to the read-only nature of Palettes, changes to the nodeDataArray, linkDataArray, or shared modelData props described above allow for a Palette's model to be changed, if necessary. |
| 152 | + |
| 153 | +```js |
| 154 | +// When the diagram model changes, update app data to reflect those changes. Be sure to preserve immutability |
| 155 | + public diagramModelChange = function(changes: go.IncrementalData) { |
| 156 | + const appComp = this; |
| 157 | + this.state = produce(this.state, draft => { |
| 158 | + // set skipsDiagramUpdate: true since GoJS already has this update |
| 159 | + draft.skipsDiagramUpdate = true; |
| 160 | + draft.diagramNodeData = DataSyncService.syncNodeData(changes, draft.diagramNodeData, appComp.observedDiagram.model); |
| 161 | + draft.diagramLinkData = DataSyncService.syncLinkData(changes, draft.diagramLinkData, appComp.observedDiagram.model); |
| 162 | + draft.diagramModelData = DataSyncService.syncModelData(changes, draft.diagramModelData); |
| 163 | + }); |
| 164 | + }; |
| 165 | +``` |
| 166 | + |
| 167 | +Notice the use of the three static functions of the `DataSyncService` (`syncNodeData`, `syncLinkData`, and `syncModelData`), which is included with this package to make syncing your app-level data with Diagram / Palette data simple. |
| 168 | +**Be aware**: If you have set your Diagram's [model.nodeKeyProperty](https://gojs.net/latest/api/symbols/Model.html#nodeKeyProperty) or [model.linkKeyProperty](https://gojs.net/latest/api/symbols/GraphLinksModel.html#linkKeyProperty) to anything other than 'key', you will need to pass your Diagram's model as a third parameter to `DataSyncService.syncNodeData` and `DataSyncService.syncLinkData`. |
| 169 | + |
| 170 | +#### observedDiagram (OverviewComponent only) |
| 171 | +Specifies the [Diagram](https://gojs.net/latest/api/symbols/Diagram.html) which the Overview will observe. |
| 172 | + |
| 173 | +## License |
| 174 | + |
| 175 | +This project is intended to be used alongside [GoJS](https://gojs.net/latest/index.html), |
| 176 | +and is covered by the GoJS <a href="https://gojs.net/latest/license.html">software license</a>. |
| 177 | + |
| 178 | +Copyright 1998-2021 by Northwoods Software Corporation. |
0 commit comments