Skip to content

Handling Annotations with Callback Functions

The annotation plugin provides callback functions that let you respond to events such as when a new annotation is created, updated, or deleted.

You can use these callbacks to sync data with your backend, trigger UI updates, or perform custom logic when users interact with annotations.

When a New Annotation is Created

Triggered whenever a new annotation is added to the viewer.

This callback provides the full annotation data, including its type, position, and metadata, allowing you to store or process it immediately after creation.

vue
<script setup lang="ts">
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import VPdfAnnotationPlugin, { type Annotation, AnnotationType } from '@vue-pdf-viewer/annotation'

function handleCreatedHighlightAnnotation(data: Annotation) {
  console.log('Created Highlight Annotation', data)
}
function handleCreatedFreeTextAnnotation(data: Annotation) {
  console.log('Created FreeText Annotation', data)
}
function handleCreatedImageAnnotation(data: Annotation) {
  console.log('Created Image Annotation', data)
}
// Custom configuration
const annotationPlugin = VPdfAnnotationPlugin({
    onAnnotationCreated: (data: Annotation) => {
      const { annotationType } = data
      switch (annotationType) {
        case AnnotationType.Highlight:
          handleCreatedHighlightAnnotation(data)
          break;
        case AnnotationType.FreeText:
          handleCreatedFreeTextAnnotation(data)
          break;
        case AnnotationType.Stamp:
          handleCreatedImageAnnotation(data)
          break;
        default:
          break;
      }
    }
  });
</script>

<template>
  <div :style="{ width: '1028px', height: '700px' }">
    <VPdfViewer 
      src="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf" 
      :plugins="[annotationPlugin]" 
    />
  </div>
</template>
vue
<script setup>
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import VPdfAnnotationPlugin, { AnnotationType } from '@vue-pdf-viewer/annotation'

function handleCreatedHighlightAnnotation(data) {
  console.log('Created Highlight Annotation', data)
}
function handleCreatedFreeTextAnnotation(data) {
  console.log('Created FreeText Annotation', data)
}
function handleCreatedImageAnnotation(data) {
  console.log('Created Image Annotation', data)
}
// Custom configuration
const annotationPlugin = VPdfAnnotationPlugin({
    onAnnotationCreated: (data) => {
      const { annotationType } = data
      switch (annotationType) {
        case AnnotationType.Highlight:
          handleCreatedHighlightAnnotation(data)
          break;
        case AnnotationType.FreeText:
          handleCreatedFreeTextAnnotation(data)
          break;
        case AnnotationType.Stamp:
          handleCreatedImageAnnotation(data)
          break;
        default:
          break;
      }
    }
  });
</script>

<template>
  <div :style="{ width: '1028px', height: '700px' }">
    <VPdfViewer 
      src="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf" 
      :plugins="[annotationPlugin]" 
    />
  </div>
</template>
vue
<script lang="ts">
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import VPdfAnnotationPlugin, { type Annotation, AnnotationType } from '@vue-pdf-viewer/annotation'
import { defineComponent } from 'vue';

export default defineComponent({
  components: { VPdfViewer },
  data() {
    return {
      annotationPlugin: {} as ReturnType<
        typeof VPdfAnnotationPlugin
      >,
    };
  },
  created() {
    this.annotationPlugin = VPdfAnnotationPlugin({
      onAnnotationCreated: (data: Annotation) => {
        const { annotationType } = data
        switch (annotationType) {
          case AnnotationType.Highlight:
            this.handleCreatedHighlightAnnotation(data)
            break;
          case AnnotationType.FreeText:
            this.handleCreatedFreeTextAnnotation(data)
            break;
          case AnnotationType.Stamp:
            this.handleCreatedImageAnnotation(data)
            break;
        }
      }
    });
  },
  methods: {
    handleCreatedHighlightAnnotation(data: Annotation) {
      console.log('Created Highlight Annotation', data)
    },
    handleCreatedFreeTextAnnotation(data: Annotation) {
      console.log('Created FreeText Annotation', data)
    },
    handleCreatedImageAnnotation(data: Annotation) {
      console.log('Created Image Annotation', data)
    },
  },
});
</script>

<template>
  <div :style="{ width: '1028px', height: '700px' }">
    <VPdfViewer 
      src="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf" 
      :plugins="[annotationPlugin]" 
    />
  </div>
</template>
vue
<script>
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import VPdfAnnotationPlugin, { AnnotationType } from '@vue-pdf-viewer/annotation'
import { defineComponent } from 'vue';

export default defineComponent({
  components: { VPdfViewer },
  data() {
    return {
      annotationPlugin: {}
    };
  },
  created() {
    this.annotationPlugin = VPdfAnnotationPlugin({
      onAnnotationCreated: (data) => {
        const { annotationType } = data
        switch (annotationType) {
          case AnnotationType.Highlight:
            this.handleCreatedHighlightAnnotation(data)
            break;
          case AnnotationType.FreeText:
            this.handleCreatedFreeTextAnnotation(data)
            break;
          case AnnotationType.Stamp:
            this.handleCreatedImageAnnotation(data)
            break;
          default:
            break;
        }
      }
    });
  },
  methods: {
    handleCreatedHighlightAnnotation(data) {
      console.log('Created Highlight Annotation', data)
    },
    handleCreatedFreeTextAnnotation(data) {
      console.log('Created FreeText Annotation', data)
    },
    handleCreatedImageAnnotation(data) {
      console.log('Created Image Annotation', data)
    },
  },
});
</script>

<template>
  <div :style="{ width: '1028px', height: '700px' }">
    <VPdfViewer 
      src="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf" 
      :plugins="[annotationPlugin]" 
    />
  </div>
</template>

When an Annotation is Updated

Triggered when an existing annotation has been modified, such as resizing, moving, or editing its content.

You can use this event to persist annotation changes to your database or update your UI to reflect the new state.

vue
<script setup lang="ts">
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import VPdfAnnotationPlugin, { type Annotation, AnnotationType } from '@vue-pdf-viewer/annotation'

function handleUpdatedHighlightAnnotation(data: Annotation) {
  console.log('Updated Highlight Annotation', data)
}
function handleUpdatedFreeTextAnnotation(data: Annotation) {
  console.log('Updated FreeText Annotation', data)
}
function handleUpdatedImageAnnotation(data: Annotation) {
  console.log('Updated Image Annotation', data)
}
// Custom configuration
const annotationPlugin = VPdfAnnotationPlugin({
    onAnnotationUpdated: (data: Annotation) => {
      const { annotationType } = data
      switch (annotationType) {
        case AnnotationType.Highlight:
          handleUpdatedHighlightAnnotation(data)
          break;
        case AnnotationType.FreeText:
          handleUpdatedFreeTextAnnotation(data)
          break;
        case AnnotationType.Stamp:
          handleUpdatedImageAnnotation(data)
          break;
        default:
          break;
      }
    }
  });
</script>

<template>
  <div :style="{ width: '1028px', height: '700px' }">
    <VPdfViewer
      src="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf"
      :plugins="[annotationPlugin]"
    />
  </div>
</template>
vue
<script setup>
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import VPdfAnnotationPlugin, { AnnotationType } from '@vue-pdf-viewer/annotation'

function handleUpdatedHighlightAnnotation(data) {
  console.log('Updated Highlight Annotation', data)
}
function handleUpdatedFreeTextAnnotation(data) {
  console.log('Updated FreeText Annotation', data)
}
function handleUpdatedImageAnnotation(data) {
  console.log('Updated Image Annotation', data)
}
// Custom configuration
const annotationPlugin = VPdfAnnotationPlugin({
    onAnnotationUpdated: (data) => {
      const { annotationType } = data
      switch (annotationType) {
        case AnnotationType.Highlight:
          handleUpdatedHighlightAnnotation(data)
          break;
        case AnnotationType.FreeText:
          handleUpdatedFreeTextAnnotation(data)
          break;
        case AnnotationType.Stamp:
          handleUpdatedImageAnnotation(data)
          break;
        default:
          break;
      }
    }
  });
</script>

<template>
  <div :style="{ width: '1028px', height: '700px' }">
    <VPdfViewer
      src="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf"
      :plugins="[annotationPlugin]"
    />
  </div>
</template>
vue
<script lang="ts">
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import VPdfAnnotationPlugin, { type Annotation, AnnotationType } from '@vue-pdf-viewer/annotation'
import { defineComponent } from 'vue';

export default defineComponent({
  components: { VPdfViewer },
  data() {
    return {
      annotationPlugin: {} as ReturnType<
        typeof VPdfAnnotationPlugin
      >,
    };
  },
  created() {
    this.annotationPlugin = VPdfAnnotationPlugin({
      onAnnotationUpdated: (data: Annotation) => {
        const { annotationType } = data
        switch (annotationType) {
          case AnnotationType.Highlight:
            this.handleUpdatedHighlightAnnotation(data)
            break;
          case AnnotationType.FreeText:
            this.handleUpdatedFreeTextAnnotation(data)
            break;
          case AnnotationType.Stamp:
            this.handleUpdatedImageAnnotation(data)
            break;
          default:
            break;
        }
      }
    });
  },
  methods: {
    handleUpdatedHighlightAnnotation(data: Annotation) {
      console.log('Updated Highlight Annotation', data)
    },
    handleUpdatedFreeTextAnnotation(data: Annotation) {
      console.log('Updated FreeText Annotation', data)
    },
    handleUpdatedImageAnnotation(data: Annotation) {
      console.log('Updated Image Annotation', data)
    },
  },
});
</script>

<template>
  <div :style="{ width: '1028px', height: '700px' }">
    <VPdfViewer
      src="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf"
      :plugins="[annotationPlugin]"
    />
  </div>
</template>
vue
<script>
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import VPdfAnnotationPlugin, { AnnotationType } from '@vue-pdf-viewer/annotation'
import { defineComponent } from 'vue';

export default defineComponent({
  components: { VPdfViewer },
  data() {
    return {
      annotationPlugin: {}
    };
  },
  created() {
    const annotationPlugin = VPdfAnnotationPlugin({
      onAnnotationUpdated: (data) => {
        const { annotationType } = data
        switch (annotationType) {
          case AnnotationType.Highlight:
            this.handleUpdatedHighlightAnnotation(data)
            break;
          case AnnotationType.FreeText:
            this.handleUpdatedFreeTextAnnotation(data)
            break;
          case AnnotationType.Stamp:
            this.handleUpdatedImageAnnotation(data)
            break;
          default:
            break;
        }
      }
    });
  },
  methods: {
    handleUpdatedHighlightAnnotation(data) {
      console.log('Updated Highlight Annotation', data)
    },
    handleUpdatedFreeTextAnnotation(data) {
      console.log('Updated FreeText Annotation', data)
    },
    handleUpdatedImageAnnotation(data) {
      console.log('Updated Image Annotation', data)
    },
  },
});
</script>

<template>
  <div :style="{ width: '1028px', height: '700px' }">
    <VPdfViewer
      src="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf"
      :plugins="[annotationPlugin]"
    />
  </div>
</template>

When an Annotation is Deleted

Triggered when an annotation is removed from the viewer.

This callback helps you keep your data in sync by removing the deleted annotation from your local or remote storage.

vue
<script setup lang="ts">
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import VPdfAnnotationPlugin, { type Annotation, AnnotationType } from '@vue-pdf-viewer/annotation'

function handleDeletedHighlightAnnotation(data: Annotation) {
  console.log('Deleted Highlight Annotation', data)
}
function handleDeletedFreeTextAnnotation(data: Annotation) {
  console.log('Deleted FreeText Annotation', data)
}
function handleDeletedImageAnnotation(data: Annotation) {
  console.log('Deleted Image Annotation', data)
}
// Custom configuration
const annotationPlugin = VPdfAnnotationPlugin({
    onAnnotationDeleted: (data: Annotation) => {
      const { annotationType } = data
      switch (annotationType) {
        case AnnotationType.Highlight:
          handleDeletedHighlightAnnotation(data)
          break;
        case AnnotationType.FreeText:
          handleDeletedFreeTextAnnotation(data)
          break;
        case AnnotationType.Stamp:
          handleDeletedImageAnnotation(data)
          break;
        default:
          break;
      }
    }
  });
</script>

<template>
  <div :style="{ width: '1028px', height: '700px' }">
    <VPdfViewer
      src="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf"
      :plugins="[annotationPlugin]"
    />
  </div>
</template>
vue
<script setup>
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import VPdfAnnotationPlugin, { AnnotationType } from '@vue-pdf-viewer/annotation'

function handleDeletedHighlightAnnotation(data) {
  console.log('Deleted Highlight Annotation', data)
}
function handleDeletedFreeTextAnnotation(data) {
  console.log('Deleted FreeText Annotation', data)
}
function handleDeletedImageAnnotation(data) {
  console.log('Deleted Image Annotation', data)
}
// Custom configuration
const annotationPlugin = VPdfAnnotationPlugin({
    onAnnotationDeleted: (data) => {
      const { annotationType } = data
      switch (annotationType) {
        case AnnotationType.Highlight:
          handleDeletedHighlightAnnotation(data)
          break;
        case AnnotationType.FreeText:
          handleDeletedFreeTextAnnotation(data)
          break;
        case AnnotationType.Stamp:
          handleDeletedImageAnnotation(data)
          break;
        default:
          break;
      }
    }
  });
</script>

<template>
  <div :style="{ width: '1028px', height: '700px' }">
    <VPdfViewer
      src="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf"
      :plugins="[annotationPlugin]"
    />
  </div>
</template>
vue
<script lang="ts">
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import VPdfAnnotationPlugin, { type Annotation, AnnotationType } from '@vue-pdf-viewer/annotation'
import { defineComponent } from 'vue';

export default defineComponent({
  components: { VPdfViewer },
  data() {
    return {
      annotationPlugin: {} as ReturnType<
        typeof VPdfAnnotationPlugin
      >,
    };
  },
  created() {
    this.annotationPlugin = VPdfAnnotationPlugin({
      onAnnotationDeleted: (data: Annotation) => {
        const { annotationType } = data
        switch (annotationType) {
          case AnnotationType.Highlight:
            this.handleDeletedHighlightAnnotation(data)
            break;
          case AnnotationType.FreeText:
            this.handleDeletedFreeTextAnnotation(data)
            break;
          case AnnotationType.Stamp:
            this.handleDeletedImageAnnotation(data)
            break;
          default:
            break;
        }
      }
    });
  },
  methods: {
    handleDeletedHighlightAnnotation(data: Annotation) {
      console.log('Deleted Highlight Annotation', data)
    },
    handleDeletedFreeTextAnnotation(data: Annotation) {
      console.log('Deleted FreeText Annotation', data)
    },
    handleDeletedImageAnnotation(data: Annotation) {
      console.log('Deleted Image Annotation', data)
    },
  },
});
</script>

<template>
  <div :style="{ width: '1028px', height: '700px' }">
    <VPdfViewer
      src="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf"
      :plugins="[annotationPlugin]"
    />
  </div>
</template>
vue
<script>
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import VPdfAnnotationPlugin, { AnnotationType } from '@vue-pdf-viewer/annotation'
import { defineComponent } from 'vue';

export default defineComponent({
  components: { VPdfViewer },
  data() {
    return {
      annotationPlugin: {}
    };
  },
  created() {
    this.annotationPlugin = VPdfAnnotationPlugin({
      onAnnotationDeleted: (data) => {
        const { annotationType } = data
        switch (annotationType) {
          case AnnotationType.Highlight:
            this.handleDeletedHighlightAnnotation(data)
            break;
          case AnnotationType.FreeText:
            this.handleDeletedFreeTextAnnotation(data)
            break;
          case AnnotationType.Stamp:
            this.handleDeletedImageAnnotation(data)
            break;
          default:
            break;
        }
      }
    });
    return {
      annotationPlugin
    }
  },
  methods: {
    handleDeletedHighlightAnnotation(data) {
      console.log('Deleted Highlight Annotation', data)
    },
    handleDeletedFreeTextAnnotation(data) {
      console.log('Deleted FreeText Annotation', data)
    },
    handleDeletedImageAnnotation(data) {
      console.log('Deleted Image Annotation', data)
    },
  },
});
</script>

<template>
  <div :style="{ width: '1028px', height: '700px' }">
    <VPdfViewer
      src="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf"
      :plugins="[annotationPlugin]"
    />
  </div>
</template>