SnapDOMGitHub★ 8K
Framework Guide · Angular 19+

Capture an Angular component

Download a signal-driven Angular view after its next render, with a typed viewChild reference and asset readiness checks.

TL;DR

Use viewChild.required to select the rendered card and afterNextRender to capture after signal updates reach the DOM. Keep the export button outside the captured element.

Install and use SnapDOM in Angular

Install the capture library in your existing Angular project:

npm install @zumer/snapdom

Add this standalone component to your Angular view.

import { Component, ElementRef, Injector, afterNextRender,
  inject, signal, viewChild } from '@angular/core'
import { snapdom } from '@zumer/snapdom'

@Component({
  selector: 'app-export-card',
  standalone: true,
  template: `
    <input aria-label="Card title" [value]="title()"
      (input)="title.set($any($event.target).value)" />
    <article #card><h2>{{ title() }}</h2><p>Ready to share.</p></article>
    <button (click)="save()" [disabled]="saving()">Download PNG</button>
    <p role="status">{{ error() }}</p>
  `,
})
export class ExportCardComponent {
  card = viewChild.required<ElementRef<HTMLElement>>('card')
  title = signal('Monthly report')
  saving = signal(false)
  error = signal('')
  private injector = inject(Injector)

  save() {
    this.saving.set(true)
    this.error.set('')
    afterNextRender(async () => {
      try {
        const el = this.card().nativeElement
        await document.fonts.ready
        await Promise.all(Array.from(el.querySelectorAll('img'), img => img.decode()))
        await snapdom.download(el, { format: 'png', filename: 'angular-card' })
      } catch (error) {
        this.error.set(error instanceof Error ? error.message : 'Capture failed')
      } finally {
        this.saving.set(false)
      }
    }, { injector: this.injector })
  }
}

Wait for Angular’s next render

The click handler may change signals, fetch data or reveal an @if block. Reading the DOM immediately after that change can capture the previous view. Angular’s afterNextRender callback runs after the next application render; pass the component’s injector when registering it from an event handler.

The example’s saving signal schedules that render. An optional viewChild can be undefined when its element is absent; use a required query only for a card that is always rendered. If the card is conditional, wait until it exists before enabling export.

Wait for data, images and fonts

Finish the application’s data request before scheduling capture. afterNextRender waits for Angular’s DOM work, not network responses. The example then waits for document.fonts.ready and decodes images inside the card; a broken image reaches the status message instead of silently producing an incomplete report.

For an exportable chart, wait for its own animation or ready event too. When the output is destined for an upload instead of a download, follow the PNG Blob and FormData pattern.

Angular SSR and hydration

Keep the export attached to a browser click. Render callbacks do not run during server-side rendering, and a server cannot provide the live layout that SnapDOM captures. For a hydrated application, wait until the component is interactive and its data has settled; a render callback alone is not a blanket guarantee that every child has completed hydration.

Frequently asked questions

Why does the PNG show the previous signal value?

The capture ran before Angular applied the signal change to the DOM. Register afterNextRender with the component injector, then capture from its callback.

Can I capture an Angular component on the server?

This recipe captures a view in the browser after it becomes interactive. Server-side screenshot jobs need a browser automation tool to load and render the route first.

Capture it in the browser

Install SnapDOM and turn the DOM your users already see into a portable image.

Open the demoInstallation