Group in Angular Diagram component

18 Dec 202324 minutes to read

Group is used to cluster multiple nodes and connectors into a single element. It acts like a container for its children (nodes, groups, and connectors). Every change made to the group also affects the children. Child elements can be edited individually.

Create group

Add group when initializing diagram

A group can be added to the diagram model through nodes collection. To define an object as group, add the child objects to the children collection of the group.

  • The padding property of a group node defines the spacing between the group node’s edges and its children.

  • While creating group, its child node need to be declared before the group declaration.

  • Add a node to the existing group child by using the diagram.group method.

  • The group’s diagram.unGroup method is used to define whether the group can be ungrouped or not.

  • A group can be added into a child of another group.

To create a group using Nodes and Connectors in the Angular Diagram, refer to the below video link,

The following code illustrates how to create a group node.

import { Component, ViewEncapsulation, OnInit, ViewChild } from '@angular/core';
import { DiagramComponent, Diagram, NodeModel, MarginModel, ShapeStyleModel } from '@syncfusion/ej2-angular-diagrams';

@Component({
    selector: "app-container",
    template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" [getNodeDefaults] ='getNodeDefaults' (created)='created($event)'>
        <e-nodes>
            <e-node id='node1' [offsetX]=100 [offsetY]=100>
            </e-node>
            <e-node id='node2' [offsetX]=200 [offsetY]=200>
            </e-node>
            <e-node id='node3' [offsetX]=400 [offsetY]=300 >
            </e-node>
            <e-node id='group' [children]='children' [padding]="padding">
            </e-node>
        </e-nodes>
    </ejs-diagram>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    @ViewChild("diagram")
    public diagram?: DiagramComponent;
    public getNodeDefaults(node: NodeModel): NodeModel {
        node.height = 100;
        node.width = 100;
        ((node as NodeModel).style as ShapeStyleModel).fill = "#6BA5D7";
        ((node as NodeModel).style as ShapeStyleModel).strokeColor = "White";
        return node;
    }
    public children?: string[];
    public padding: MarginModel = {left:10,right:10,top:10,bottom:10}
    ngOnInit(): void {
        this.children = ['node1', 'node2']
    }
    public created(args: Object): void {
        (this.diagram as DiagramComponent).selectAll();
        // Adding the third node into the existing group
        (this.diagram as DiagramComponent).group();
    }
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { DiagramModule } from '@syncfusion/ej2-angular-diagrams';

/**
 * Module
 */
@NgModule({
    imports: [
        BrowserModule, DiagramModule
    ],
    declarations: [AppComponent],
    bootstrap: [AppComponent],
    providers: [ ]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);

The following code illustrates how a ungroup at runtime.

import { Component, ViewEncapsulation, OnInit, ViewChild } from '@angular/core';
import { DiagramComponent, Diagram, NodeModel, ShapeStyleModel } from '@syncfusion/ej2-angular-diagrams';

@Component({
    selector: "app-container",
    template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" [getNodeDefaults] ='getNodeDefaults' (created)='created($event)'>
        <e-nodes>
            <e-node id='node1' [offsetX]=100 [offsetY]=100>
            </e-node>
            <e-node id='node2' [offsetX]=200 [offsetY]=200>
            </e-node>
            <e-node id='node3' [offsetX]=400 [offsetY]=300 >
            </e-node>
            <e-node id='group' [children]='children'>
            </e-node>
        </e-nodes>
    </ejs-diagram>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    @ViewChild("diagram")
    public diagram?: DiagramComponent;
    public getNodeDefaults(node: NodeModel): NodeModel {
        node.height = 100;
        node.width = 100;
        ((node as NodeModel).style as ShapeStyleModel).fill = "#6BA5D7";
        ((node as NodeModel).style as ShapeStyleModel).strokeColor = "White";
        return node;
    }
    public children?: string[];
    ngOnInit(): void {
        this.children = ['node1', 'node2']
    }
    public created(args: Object): void {
        (this.diagram as DiagramComponent).selectAll();
        // Ungroup the selected group into nodes
        (this.diagram as DiagramComponent).unGroup();
    }
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { DiagramModule } from '@syncfusion/ej2-angular-diagrams';

/**
 * Module
 */
@NgModule({
    imports: [
        BrowserModule, DiagramModule
    ],
    declarations: [AppComponent],
    bootstrap: [AppComponent],
    providers: [ ]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);

Connectors can be added to a group. The following code illustrates how to add connectors into a group.

import { Component, ViewEncapsulation, ViewChild, } from '@angular/core';
import {
    DiagramComponent, NodeModel, ConnectorModel,
} from '@syncfusion/ej2-angular-diagrams';

@Component({
    selector: 'app-container',
    template: `<ejs-diagram #diagram id="diagram" width="1000px" height="700px" [nodes]='nodes' [connectors]="connectors">
    </ejs-diagram>`,
    encapsulation: ViewEncapsulation.None
})

export class AppComponent {
    @ViewChild('diagram')
    public diagram?: DiagramComponent;
    public connectors: ConnectorModel[] = [{
      id: 'connector1', type: 'Orthogonal', sourceID: 'node1', targetID: 'node2'
    },
   ];
    public nodes: NodeModel[] = [{
     id: 'node1', height: 100, width: 100, offsetX: 100, offsetY: 100, annotations: [{ content: 'Node1'}]
   },
   {
     id: 'node2', height: 100, width: 100, offsetX: 300, offsetY: 100, annotations: [{ content: 'Node2'}]
   },
   {
     id: 'group', children: ['node1', 'node2', 'connector1',], style: { strokeWidth: 0}
   }];
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { DiagramModule } from '@syncfusion/ej2-angular-diagrams';

/**
 * Module
 */
@NgModule({
    imports: [
        BrowserModule, DiagramModule
    ],
    declarations: [AppComponent],
    bootstrap: [AppComponent],
    providers: [ ]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);

Add group at runtime

A group node can be added at runtime by using the client-side method diagram.add.

The following code illustrates how a group node is added at runtime.

import { Component, ViewEncapsulation, OnInit, ViewChild } from '@angular/core';
import { DiagramComponent, Diagram, NodeModel, ShapeStyleModel } from '@syncfusion/ej2-angular-diagrams';

@Component({
    selector: "app-container",
    template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" [getNodeDefaults] ='getNodeDefaults' (created)='created($event)'>
        <e-nodes>
            <e-node id='node1' [offsetX]=100 [offsetY]=100>
            </e-node>
            <e-node id='node2' [offsetX]=200 [offsetY]=200>
            </e-node>
        </e-nodes>
    </ejs-diagram>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    @ViewChild("diagram")
    public diagram?: DiagramComponent;
    public getNodeDefaults(node: NodeModel): NodeModel {
        node.height = 100;
        node.width = 100;
        ((node as NodeModel).style as ShapeStyleModel).fill = "#6BA5D7";
        ((node as NodeModel).style as ShapeStyleModel).strokeColor = "White";
        return node;
    }
    public group: NodeModel[] = [{
            id: 'group2',
            children: ['node1', 'node2']
        }]
    public created(args: Object): void {
        // Add the group into the diagram
        (this.diagram as DiagramComponent).add(this.group as any);
    }
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { DiagramModule } from '@syncfusion/ej2-angular-diagrams';

/**
 * Module
 */
@NgModule({
    imports: [
        BrowserModule, DiagramModule
    ],
    declarations: [AppComponent],
    bootstrap: [AppComponent],
    providers: [ ]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);

Add children To group at runtime

A childNode can be added to the specified Group at runtime by utilizing the client-side method diagram.addChildToGroup.

This functionality is achieved by passing the group and existing children as arguments to the method.

The following code illustrates how a child node and a group node can be passed as arguments to the method and executed at runtime.

this.diagram.addChildToGroup(groupNode, childNode);

Remove children from group at runtime

A specific child from a group node can be removed at runtime by utilizing the client-side method diagram.removeChildFromGroup .

This functionality is achieved by passing the group and its children as arguments to the method.

The following code illustrates how a child node is removed from a group at runtime.

this.diagram.removeChildFromGroup (groupNode, childNode);
import { Component, ViewEncapsulation, OnInit, ViewChild } from '@angular/core';
import { DiagramComponent, Diagram, NodeModel } from '@syncfusion/ej2-angular-diagrams';

@Component({
    selector: "app-container",
    template: `
    <button (click)="addChild()">addChild</button>
    <button (click)="removeChild()">removeChild</button>
    <ejs-diagram #diagram id="diagram" width="100%" height="600" [nodes]="nodes" >
    </ejs-diagram>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    @ViewChild("diagram")
    public diagram?: DiagramComponent;
    public nodes?: NodeModel[];

    addChild() {
        (this.diagram as any).addChildToGroup(
          (this.diagram as any).nodes[2],
          'node3'
        );
    }
    removeChild() {
        (this.diagram as any).removeChildFromGroup(
          (this.diagram as any).nodes[2],
          'node3'
        );
    }
  
    ngOnInit(): void {

        this.nodes = [
            {
                id: 'node1', width: 150, height: 100, offsetX: 100, offsetY: 100, annotations: [{ content: 'Node1' }]
            }, {
                id: 'node2', width: 80, height: 130, offsetX: 200, offsetY: 200, annotations: [{ content: 'Node2' }]
            }, {
                id: 'group1', children: ['node1', 'node2']
            }, {
                id: 'node3', width: 100, height: 100, offsetX: 300, offsetY: 300, annotations: [{ content: 'Node3' }]
            }
        ];

    }
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { DiagramModule } from '@syncfusion/ej2-angular-diagrams';

/**
 * Module
 */
@NgModule({
    imports: [
        BrowserModule, DiagramModule
    ],
    declarations: [AppComponent],
    bootstrap: [AppComponent],
    providers: [ ]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);

Container

Containers are used to automatically measure and arrange the size and position of the child elements in a predefined manner.

There are two types of containers available.

  • Canvas
  • Stack

Canvas

  • The canvas panel supports absolute positioning and provides the least layout functionality to its contained diagram elements.

  • Canvas allows you to position its contained elements by using the margin and alignment properties.

  • Rendering alone possible in canvas container.

  • It allows elements to be either vertically or horizontally aligned.

  • Child can be defined with the collection canvas.children property.

  • Basic element can be defined with the collection of basicElements.

Stack

  • Stack panel is used to arrange its children in a single line or stack order, either vertically or horizontally.

  • It controls spacing by setting margin properties of child and padding properties of group. By default, a stack panel’s orientation is vertical.

The following code illustrates how to add a stack panel.

import { Component, ViewEncapsulation, OnInit, ViewChild } from '@angular/core';
import { DiagramComponent, Diagram, NodeModel, TextElement, StackPanel, PointModel, VerticalAlignment, ShapeStyleModel } from '@syncfusion/ej2-angular-diagrams';

@Component({
    selector: "app-container",
    template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" [getNodeDefaults] ='getNodeDefaults'>
        <e-nodes>
            <e-node id='node1' [offsetX]=100 [offsetY]=100>
                <e-node-annotations>
                    <e-node-annotation content="Custom Template" [offset]='offset' [verticalAlignment]='verticalAlignment'>
                </e-node-annotation>
        </e-node-annotations>
            </e-node>
        </e-nodes>
    </ejs-diagram>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    @ViewChild("diagram")
    public diagram?: DiagramComponent;
    public offset?: PointModel
    public verticalAlignment?: VerticalAlignment
    public getTextElement(text: string): TextElement {
        let textElement: TextElement = new TextElement();
        textElement.width = 50;
        textElement.height = 20;
        textElement.content = text;
        return textElement;
    };

    public addRows(column: StackPanel) {
        column.children.push(this.getTextElement('Row1'));
        column.children.push(this.getTextElement('Row2'));
        column.children.push(this.getTextElement('Row3'));
        column.children.push(this.getTextElement('Row4'));
    };
    public getNodeDefaults(node: NodeModel): NodeModel {
        node.height = 100;
        node.width = 100;
        ((node as NodeModel).style as ShapeStyleModel).fill = '#6BA5D7';
        ((node as NodeModel).style as ShapeStyleModel).strokeColor = 'white';
        return node;
    }
    ngOnInit(): void {
        this.verticalAlignment = 'Top';
        this.offset = {y: 1};
        (this.diagram as DiagramComponent).setNodeTemplate = (obj: NodeModel | any, diagram: Diagram): StackPanel | any => {
            if (obj.id.indexOf('node1') !== -1) {
                // It will be replaced with grid panel
                let table: StackPanel = new StackPanel();
                table.orientation = 'Horizontal';
                let column1: StackPanel = new StackPanel();
                column1.children = [];
                column1.children.push(this.getTextElement('Column1'));
                this.addRows(column1);
                let column2: StackPanel = new StackPanel();
                column2.children = [];
                column2.children.push(this.getTextElement('Column2'));
                this.addRows(column2);
                table.children = [column1, column2];
                return table;
            }
            return undefined;
        }
    }
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { DiagramModule } from '@syncfusion/ej2-angular-diagrams';

/**
 * Module
 */
@NgModule({
    imports: [
        BrowserModule, DiagramModule
    ],
    declarations: [AppComponent],
    bootstrap: [AppComponent],
    providers: [ ]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);

Difference between a basic group and containers

Group Container
It arranges the child elements based on the child elements position and size properties. Each container has a predefined behavior to measure and arrange its child elements. Canvas and stack containers are supported in the diagram.
The Padding, Min, and Max Size properties are not applicable for basic group. It is applicable for container.
The Children’s margin and alignment properties are not applicable for basic group. It is applicable for container.

Interaction

You can edit the group and its children at runtime. For more information about how to interact with a group, refer to Edit Groups.

See Also