Errors
When the viewer is set up in a way that can’t work, the Angular package throws an error with a
number, such as EPDF-101, says how to fix it, and links here. Each section below is one number:
what happened, and the fix.
A document that isn’t open yet, or a permission the user doesn’t have, isn’t a setup mistake: a
plugin refuses those with a PluginError (not-ready, permission-denied), the same in every
framework. See Permissions.
EPDF-101#
No viewer above it. A service of the viewer (inject(EpdfDocuments), inject(EpdfViewer))
or one of its components (<epdf-stage>, *epdfDocumentGate) found no provideEmbedPdf() in
the component that uses it or in any component above it.
Add provideEmbedPdf() to the providers of the component that shows the viewer. That component
and everything in its template share the viewer, and the component can inject it itself:
import { Component, inject } from '@angular/core';
import { EpdfDocuments, provideEmbedPdf } from '@embedpdf/angular/runtime';
import { withRender } from '@embedpdf/angular/render';
import { withStage } from '@embedpdf/angular/stage';
import { DownloadButton } from './download-button';
import { engine } from './pdf';
@Component({
selector: 'app-document-viewer',
imports: [DownloadButton],
// The viewer, for this component and everything in its template
providers: [provideEmbedPdf({ engine }, withStage(), withRender())],
template: `<app-download-button />`,
})
export class DocumentViewer {
// This component can inject it too
private readonly documents = inject(EpdfDocuments);
}For one viewer in the whole app, put the same call in app.config.ts; for one per route, in the
route’s providers. A component outside the one that provides the viewer, such as a sibling in
your layout, can’t reach it: move provideEmbedPdf() up to a component both are inside.
EPDF-102#
No viewer with this plugin. A plugin’s service (inject(EpdfRender), inject(EpdfSearch))
found no viewer above it that has the plugin. Either there’s no viewer above it at all, or the
viewer’s provideEmbedPdf() doesn’t have the plugin’s feature.
Add the feature the error names to provideEmbedPdf(), in the component that provides the viewer
or in your app config. withRender() gives EpdfRender, withSearch() gives EpdfSearch, and
so on:
import { Component, inject } from '@angular/core';
import { provideEmbedPdf } from '@embedpdf/angular/runtime';
import { EpdfRender, withRender } from '@embedpdf/angular/render';
import { withStage } from '@embedpdf/angular/stage';
import { engine } from './pdf';
@Component({
selector: 'app-document-viewer',
// withRender() is what gives the viewer EpdfRender
providers: [provideEmbedPdf({ engine }, withStage(), withRender())],
template: `<!-- your toolbar and pages -->`,
})
export class DocumentViewer {
private readonly render = inject(EpdfRender);
}EPDF-103#
A layer outside a page. Something that draws on a page, such as <epdf-render-layer>, isn’t
inside a page. A layer needs the page it draws on, and only the Stage gives one.
Put it inside <ng-template epdfPage> in an <epdf-stage>. The Stage draws that template once
for every page on screen:
import { Component } from '@angular/core';
import { EpdfRenderLayer } from '@embedpdf/angular/render';
import { EpdfPageTemplate, EpdfStage } from '@embedpdf/angular/stage';
@Component({
selector: 'app-pages',
imports: [EpdfStage, EpdfPageTemplate, EpdfRenderLayer],
template: `
<epdf-stage>
<ng-template epdfPage>
<!-- Drawn once on every page -->
<epdf-render-layer />
</ng-template>
</epdf-stage>
`,
})
export class Pages {}EPDF-104#
Part of a Stage outside one. UI that belongs to a Stage, such as <epdf-scrollbar> or
<epdf-anchored>, isn’t inside an <epdf-stage>. It scrolls that Stage, or follows its pages,
so it needs to be in it.
Put it between the Stage’s tags, next to the page template. It sits over the pages, in the Stage’s own box:
import { Component } from '@angular/core';
import { EpdfRenderLayer } from '@embedpdf/angular/render';
import { EpdfPageTemplate, EpdfScrollbar, EpdfStage } from '@embedpdf/angular/stage';
@Component({
selector: 'app-pages',
imports: [EpdfStage, EpdfPageTemplate, EpdfRenderLayer, EpdfScrollbar],
template: `
<epdf-stage>
<ng-template epdfPage>
<epdf-render-layer />
</ng-template>
<!-- Inside the Stage, over its pages -->
<epdf-scrollbar axis="y" />
</epdf-stage>
`,
})
export class Pages {}EPDF-105#
An engine call on the server. Code called a method that needs the engine (open(), a page’s
picture, a zoom) while Angular rendered the page on the server. The engine only runs in the
browser, so on the server the viewer renders its empty state and every such call throws.
Call it from something that only happens in the browser: an event handler ((click)), or
afterNextRender() for work when the component first shows:
import { afterNextRender, Component, inject } from '@angular/core';
import { EpdfDocuments } from '@embedpdf/angular/runtime';
@Component({
selector: 'app-contract',
template: `<!-- your toolbar and pages -->`,
})
export class Contract {
private readonly documents = inject(EpdfDocuments);
constructor() {
// Runs in the browser only, after the first render
afterNextRender(() => {
void this.documents.open({ kind: 'url', url: '/files/contract.pdf' });
});
}
}To keep the viewer out of the server render altogether, put it in a @defer (on viewport)
block. See Setup.
Your feedback goes directly to the documentation team.