> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/web/annotation/annotationmanager/grouping.md).

# Grouping annotations through the AnnotationManager

Learn how to group annotations using AnnotationManager for web. Keep annotations together for more meaningful commentary on your documents. Group and ungroup annotations easily, both in the UI and pro

Grouping annotations can be done in WebViewer both in the UI and programmatically. This can be useful for keeping annotations together and forming more meaningful commentary on your documents. Grouped annotations associate themselves to one primary annotation. Only the comment of the primary annotation will appear in the notes panel.

This is what grouped annotations look like represented in XFDF:

{% tabs %}
{% tab title="Shell" %}
{% code lineNumbers="true" %}

```sh
<square page="0" rect="92.533,616.387,228.861,717.911" color="#E44234" flags="print" name="f1b0896d-b173-c01e-27bf-eee16f33ae23" title="Guest" subject="Rectangle" rotation="345.166" date="D:20220411125212-07'00'" creationdate="D:20220411125149-07'00'" />
<circle page="0" rect="141.590,547.820,264.010,660.970" color="#E44234" flags="print" inreplyto="f1b0896d-b173-c01e-27bf-eee16f33ae23" replyType="group" name="c245310b-3704-41ea-46ca-756bd66217ae" title="Guest" subject="Ellipse" date="D:20220411125212-07'00'" creationdate="D:20220411125152-07'00'"/>
```

{% endcode %}
{% endtab %}
{% endtabs %}

Notice the `replyType` and `inreplyto` attributes of the `circle` annotation which refer to the `square` annotation as the primary.

## Grouping annotations in the UI

Grouping annotations through the UI is straightforward. Simply selection the annotations you want to group and press the group button.

![](https://3532544125-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FX9YnTSKIHvV7m0A36LbO%2Fuploads%2Fgit-blob-a83bda368e9739a5dfc61b7d71d3e3477b11e55d%2F9c3976800165adc7ab9e7c2c8dfd485a76a506f2-326x335.png?alt=media)

## Ungrouping annotations in the UI

Likewise, ungrouping annotations will require first selecting the group and pressing the ungroup button.

![](https://3532544125-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FX9YnTSKIHvV7m0A36LbO%2Fuploads%2Fgit-blob-9491c46a057473440376ae1b4f2576bc4bff1a38%2F567c173b7c31a168937324f9e20908a0b265dcf9-312x311.png?alt=media)

## Grouping annotations programmatically

Grouping annotations is done through the AnnotationManager. The API is called [`groupAnnotations`](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#groupAnnotations__anchor) and it takes a primary annotation along with an array of annotations that will be grouped with it.

{% tabs %}
{% tab title="JavaScript (SDK v8.0+)" %}
{% code lineNumbers="true" %}

```js
const { annotationManager } = instance.Core;

const annotList = annotationManager.getAnnotationsList();
const primaryAnnot = annotList[0];
const primaryColor = primary.FillColor.toHexString();
// Group annotations of the same color
const secondaryAnnots = annotList.filter(annot => annot.FillColor.toHexString() === primaryColor);

annotationManager.groupAnnotations(primary, secondary);
```

{% endcode %}

[AnnotationManager.getAnnotationsList](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#getAnnotationsList__anchor) [AnnotationManager.groupAnnotations](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#groupAnnotations__anchor) [Color.toHexString](https://sdk.apryse.com/api/web/Core.Annotations.Color.html#toHexString__anchor)
{% endtab %}

{% tab title="JavaScript (SDK v6.0+)" %}
{% code lineNumbers="true" %}

```js
const { annotManager } = instance;

const annotList = annotManager.getAnnotationsList();
const primaryAnnot = annotList[0];
const primaryColor = primary.FillColor.toHexString();
// Group annotations of the same color
const secondaryAnnots = annotList.filter(annot => annot.FillColor.toHexString() === primaryColor);

annotManager.groupAnnotations(primary, secondary);
```

{% endcode %}

[AnnotationManager.getAnnotationsList](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#getAnnotationsList__anchor) [AnnotationManager.groupAnnotations](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#groupAnnotations__anchor) [Color.toHexString](https://sdk.apryse.com/api/web/Core.Annotations.Color.html#toHexString__anchor)
{% endtab %}
{% endtabs %}

{% hint style="info" %}
You can group annotations that are on different pages. However, the group's movement will still be constrained by their respective pages.
{% endhint %}

Grouping an annotation to a group will create another group instead of adding to it, so you must always group to the primary annotation to add a new annotation to the group.

## Ungrouping annotations programmatically

Simlar to grouping annotations, the AnnotationManager also provides the [`ungroupAnnotations`](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#ungroupAnnotations__anchor) function. This function takes an array of annotations to be ungrouped (regardless of which group they belong in) and it will ungroup them without ungrouping other annotations of their respective groups.

{% tabs %}
{% tab title="JavaScript (SDK v8.0+)" %}
{% code lineNumbers="true" %}

```js
const { annotationManager } = instance.Core;

const annotList = annotationManager.getAnnotationsList();
const groupedAnnots = annotList.filter(annot => annot.isGrouped() && annot.PageNumber === 1);
annotationManager.ungroupAnnotations(groupedAnnots);
```

{% endcode %}

[AnnotationManager.groupAnnotations](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#ungroupAnnotations__anchor)
{% endtab %}

{% tab title="JavaScript (SDK v6.0+)" %}
{% code lineNumbers="true" %}

```js
const { annotManager } = instance.Core;

const annotList = annotManager.getAnnotationsList();
const groupedAnnots = annotList.filter(annot => annot.isGrouped() && annot.PageNumber === 1);
annotManager.ungroupAnnotations(groupedAnnots);
```

{% endcode %}

[AnnotationManager.groupAnnotations](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#ungroupAnnotations__anchor)
{% endtab %}
{% endtabs %}

## Reading grouped annotations

A helpful API that will get you all the grouped annotations (both the primary and children) is the [`getGroupAnnotations`](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#ggetGroupAnnotations) API. By passing in any of the annotations that are part of the group, it will provide all the annotations in the group including that one that was passed in.

{% tabs %}
{% tab title="JavaScript (SDK v8.0+)" %}
{% code lineNumbers="true" %}

```js
const { annotationManager } = instance.Core;

const annotList = annotationManager.getAnnotationsList();
annotList.forEach(annot => {
  const group = annotationManager.getGroupAnnotations(annot);
  console.log(group);
});
```

{% endcode %}

[AnnotationManager.getGroupAnnotations](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#getGroupAnnotations__anchor)
{% endtab %}

{% tab title="JavaScript (SDK v6.0+)" %}
{% code lineNumbers="true" %}

```js
const { annotManager } = instance;

const annotList = annotManager.getAnnotationsList();
annotList.forEach(annot => {
  const group = annotManager.getGroupAnnotations(annot);
  console.log(group);
});
```

{% endcode %}

[AnnotationManager.getGroupAnnotations](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#getGroupAnnotations__anchor)
{% endtab %}
{% endtabs %}

Although this will return both the primary and the children annotations, it may be helpful to be able to make a distinction between them. The next sections will cover this.

### Using `isGrouped`

The [`isGrouped`](https://sdk.apryse.com/api/web/Core.Annotations.Annotation.html#isGrouped__anchor) API on annotations will tell you whether the annotation is grouped with another. This will only get you secondary annotations that are grouped to a primary annotation. You can leverage this to determine both the parent and children.

{% tabs %}
{% tab title="JavaScript (SDK v8.0+)" %}
{% code lineNumbers="true" %}

```js
const { annotationManager } = instance.Core;

const annotList = annotationManager.getAnnotationsList();
annotList.forEach(annot => {
  const group = annotationManager.getGroupAnnotations(annot);
  const parent = group.find(annot => !annot.isGrouped());
  const children = group.filter(annot => annot.isGrouped());

  // Use annotations
});
```

{% endcode %}

[Annotation.isGrouped](https://sdk.apryse.com/api/web/Core.Annotations.Annotation.html#isGrouped__anchor)
{% endtab %}

{% tab title="JavaScript (SDK v6.0+)" %}
{% code lineNumbers="true" %}

```js
const { annotManager } = instance;

const annotList = annotManager.getAnnotationsList();
annotList.forEach(annot => {
  const group = annotManager.getGroupAnnotations(annot);
  const parent = group.find(annot => !annot.isGrouped());
  const children = group.filter(annot => annot.isGrouped());

  // Use annotations
});
```

{% endcode %}

[Annotation.isGrouped](https://sdk.apryse.com/api/web/Core.Annotations.Annotation.html#isGrouped__anchor)
{% endtab %}
{% endtabs %}

### Getting the primary annotation with `InReplyTo`

Alternatively, you can make use of the [`InReplyTo`](https://sdk.apryse.com/api/web/Core.Annotations.Annotation.html#InReplyTo) property of a grouped secondary annotation along with [`getAnnotationById`](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#getAnnotationById) on the AnnotationManager to get the primary annotation.

{% tabs %}
{% tab title="JavaScript (SDK v8.0+)" %}
{% code lineNumbers="true" %}

```js
const primaryAnnotsMap = {};
groupedAnnots.forEach(annot => {
  const primary = annotationManager.getAnnotationById(annot.InReplyTo);
  if (primaryAnnotsMap[primary.Id]) {
    return;
  }
  primaryAnnotsMap[primary.Id] = primary;
});
const primaryAnnots = Object.values(primaryAnnotsMap);
```

{% endcode %}

[Annotation.InReplyTo](https://sdk.apryse.com/api/web/Core.Annotations.Annotation.html#InReplyTo) [AnnotationManager.getAnnotationById](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#getAnnotationById)
{% endtab %}

{% tab title="JavaScript (SDK v6.0+)" %}
{% code lineNumbers="true" %}

```js
const primaryAnnotsMap = {};
groupedAnnots.forEach(annot => {
  const primary = annotManager.getAnnotationById(annot.InReplyTo);
  if (primaryAnnotsMap[primary.Id]) {
    return;
  }
  primaryAnnotsMap[primary.Id] = primary;
});
const primaryAnnots = Object.values(primaryAnnotsMap);
```

{% endcode %}

[Annotation.InReplyTo](https://sdk.apryse.com/api/web/Core.Annotations.Annotation.html#InReplyTo) [AnnotationManager.getAnnotationById](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#getAnnotationById)
{% endtab %}
{% endtabs %}

### Getting grouped children using the primary annotation

If you have the primary annotation of a group, you can use [`getGroupedChildren`](https://sdk.apryse.com/api/web/Core.Annotations.Annotation.html#getGroupedChildren) to get all the child annotations that are grouped with it. You could also use this to check for a primary annotation.

{% tabs %}
{% tab title="JavaScript (SDK v8.0+)" %}
{% code lineNumbers="true" %}

```js
const annotList = annotationManager.getAnnotationsList();
annotList.forEach(primary => {
  const children = primary.getGroupedChildren();
  if (children.length > 0) {
    // This is a primary annotation
  }
});
```

{% endcode %}

[Annotation.getGroupedChildren](https://sdk.apryse.com/api/web/Core.Annotations.Annotation.html#getGroupedChildren)
{% endtab %}

{% tab title="JavaScript (SDK v6.0+)" %}
{% code lineNumbers="true" %}

```js
const annotList = annotManager.getAnnotationsList();
annotList.forEach(primary => {
  const children = primary.getGroupedChildren();
  if (children.length > 0) {
    // This is a primary annotation
  }
});
```

{% endcode %}

[Annotation.getGroupedChildren](https://sdk.apryse.com/api/web/Core.Annotations.Annotation.html#getGroupedChildren)
{% endtab %}
{% endtabs %}

## Next steps

Look into how you can [create](/web/annotation/create-annotations.md) your own annotations!


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/web/annotation/annotationmanager/grouping.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
