Skip to content
Merged
20 changes: 1 addition & 19 deletions apps/angular-demo/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,8 @@ export class AppComponent {
type: 'image',
position: { x: 100, y: 50 },
data: { imageUrl: 'https://tinyurl.com/bddnt44s' },
resizable: true,
},
{ id: '2', type: 'input-field', position: { x: 400, y: 100 }, data: {}, resizable: true },
{ id: '2', type: 'input-field', position: { x: 400, y: 100 }, data: {} },
{
id: '3',
type: 'resizable',
Expand All @@ -131,64 +130,47 @@ export class AppComponent {
id: '4',
position: { x: 800, y: 350 },
data: {},
resizable: true,
isGroup: true,
},
{
id: '5',
position: { x: 100, y: 250 },
data: { label: 'edge is manual' },
resizable: true,
rotatable: true,
},
{
id: '6',
position: { x: 463, y: 382 },
data: { label: "so it's ok it's unconnected after move" },
resizable: true,
rotatable: true,
},
{
id: '7',
position: { x: 100, y: 450 },
data: {},
resizable: true,
rotatable: true,
},
{
id: '8',
position: { x: 550, y: 550 },
data: {},
resizable: true,
rotatable: true,
},
{
id: '9',
position: { x: 100, y: 650 },
data: { label: 'just bezier edge' },
resizable: true,
rotatable: true,
},
{
id: '10',
position: { x: 450, y: 750 },
data: {},
resizable: true,
rotatable: true,
},
{
id: '11',
position: { x: 600, y: 650 },
data: { label: 'test linking' },
resizable: true,
rotatable: true,
},
{
id: '12',
position: { x: 1000, y: 550 },
data: {},
resizable: true,
rotatable: true,
},
],
edges: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ export class DiagramComponent {
} satisfies NgDiagramConfig;
// @collapse-start:config

// @section-start:enabling
model = initializeModel({
nodes: [
{
Expand All @@ -62,17 +61,11 @@ export class DiagramComponent {
autoSize: false,
type: 'myType',
data: {},
// @mark-start:enabling
resizable: true,
// @mark-end:enabling
},
],
// @collapse-start:enabling
edges: [],
metadata: { viewport: { x: 0, y: 0, scale: 1 } },
// @collapse-end:enabling
});
// @section-end:enabling
// @collapse-end:config
}
// @section-end:config
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@use '../../../../../styles/shared.scss' as *;
@use '../../../../../../styles/shared.scss' as *;

:host {
@include custom-node__host;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
:host {
display: flex;
position: relative;
}

.diagram {
display: flex;
width: 100%;
height: 20rem;
}

.toolbar {
position: absolute;
top: 0;
right: 0;
display: flex;
z-index: 1;
flex-direction: column;
align-items: flex-end;
background-color: var(--ngd-ui-bg-tertiary-default);
margin-top: 1rem;

button {
margin-top: 0;
}

div {
display: flex;
gap: 0.5rem;
align-items: center;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import '@angular/compiler';
import { Component, computed, inject } from '@angular/core';
import {
initializeModel,
NgDiagramComponent,
NgDiagramModelService,
NgDiagramService,
provideNgDiagram,
type NgDiagramNodeTemplateMap,
type Node,
type SelectionChangedEvent,
} from 'ng-diagram';

import { CustomNodeComponent } from './node/node.component';

@Component({
imports: [NgDiagramComponent],
providers: [provideNgDiagram()],
template: `
<div class="toolbar">
<form>
<div>
<span>NgDiagramConfig defaultResizable:</span>
<select
id="resizable-select"
(change)="setGlobalResizable($any($event.target).value)"
[value]="flowConfigResizable().toString()"
>
<option value="true">True</option>
<option value="false">False</option>
</select>
</div>
</form>
@if (selectedNode?.type === 'myType') {
<form>
<div>
<span>Resize Adornment defaultResizable:</span>
<select
id="adornment-resizable-select"
(change)="setNodeAdornmentResizable($any($event.target).value)"
[value]="selectedNode.data?.resizable?.toString() ?? 'undefined'"
>
<option value="true">True</option>
<option value="false">False</option>
<option value="undefined">Undefined</option>
</select>
</div>
</form>
}
@if (selectedNode) {
<form>
<div>
<span>Node Data resizable:</span>
<select
id="node-resizable-toggle"
(change)="setNodeResizable($any($event.target).value)"
[value]="selectedNode.resizable?.toString() ?? 'undefined'"
>
<option value="true">True</option>
<option value="false">False</option>
<option value="undefined">Undefined</option>
</select>
</div>
</form>
}
</div>
<div class="not-content diagram">
<ng-diagram
[model]="model"
[nodeTemplateMap]="nodeTemplateMap"
(selectionChanged)="onSelectionChange($event)"
/>
</div>
`,
styleUrls: ['./diagram.component.scss'],
})
export class DiagramComponent {
private ngDiagramService = inject(NgDiagramService);
private modelService = inject(NgDiagramModelService);
nodeTemplateMap: NgDiagramNodeTemplateMap = new Map([
['myType', CustomNodeComponent],
]);
selectedNode: Node | null = null;
flowConfigResizable = computed(
() => this.ngDiagramService.config().resize?.defaultResizable ?? false
);

onSelectionChange(event: SelectionChangedEvent) {
this.selectedNode = event.selectedNodes.length
? event.selectedNodes[0]
: null;
}

private parseValue(value: string): boolean | undefined {
if (value === 'true') {
return true;
} else if (value === 'false') {
return false;
}
return undefined;
}

setGlobalResizable(value: string) {
this.ngDiagramService.updateConfig({
resize: {
defaultResizable: value === 'true',
},
});
}

setNodeResizable(value: string) {
if (!this.selectedNode) {
return;
}
this.modelService.updateNode(this.selectedNode.id, {
resizable: this.parseValue(value),
});
}

setNodeAdornmentResizable(value: string) {
if (!this.selectedNode) {
return;
}
this.modelService.updateNodeData(this.selectedNode.id, {
resizable: this.parseValue(value),
});
}

// @section-start:model
model = initializeModel({
nodes: [
{
id: '1',
position: { x: 150, y: 150 },
autoSize: false,
type: 'myType',
data: { adornmentResizable: true },
resizable: false,
},
{
id: '2',
position: { x: 400, y: 150 },
data: { label: 'Default node' },
},
],
edges: [],
metadata: { viewport: { x: 0, y: 0, scale: 1 } },
});
// @section-end:model
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
import { DiagramComponent } from './diagram.component';
---

<DiagramComponent client:only="angular" />
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@use '../../../../../styles/shared.scss' as *;
@use '../../../../../../styles/shared.scss' as *;

:host {
@include custom-node__host;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// @collapse-start
import { Component, computed, input } from '@angular/core';
import {
NgDiagramNodeResizeAdornmentComponent,
NgDiagramNodeSelectedDirective,
type NgDiagramNodeTemplate,
type Node,
} from 'ng-diagram';
// @collapse-end

@Component({
imports: [NgDiagramNodeResizeAdornmentComponent],
template: `
<ng-diagram-node-resize-adornment [defaultResizable]="defaultResizable()">
<div class="custom-node">
<div class="custom-node__header">Custom node</div>
</div>
</ng-diagram-node-resize-adornment>
`,
hostDirectives: [
{ directive: NgDiagramNodeSelectedDirective, inputs: ['node'] },
],
styleUrls: ['./node.component.scss'],
})
export class CustomNodeComponent implements NgDiagramNodeTemplate {
node = input.required<Node<{ adornmentResizable?: boolean }>>();
defaultResizable = computed(() => this.node().data['adornmentResizable']);
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,6 @@ export class DiagramComponent {
autoSize: false,
type: 'myType',
data: {},
// @mark-start:enabling
rotatable: true,
// @mark-end:enabling
},
],
// @collapse-start:enabling
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@use '../../../../../../styles/shared.scss' as *;

:host {
@include custom-node__host;

.custom-node {
&__header {
@include custom-node__header;
}

&__content {
@include custom-node__content;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
:host {
display: flex;
position: relative;
}

.diagram {
display: flex;
width: 100%;
height: 20rem;
}

.toolbar {
position: absolute;
top: 0;
right: 0;
display: flex;
z-index: 1;
flex-direction: column;
align-items: flex-end;
background-color: var(--ngd-ui-bg-tertiary-default);
margin-top: 1rem;

button {
margin-top: 0;
}

div {
display: flex;
gap: 0.5rem;
align-items: center;
}
}
Loading