Skip to content

Angular adapter error calling mount in SSR #56

Description

@marcjulian

While using Angular Chart adapter the following code throws an error only in Angular SSR, no error is thrown in the browser.

Here is an example chart, to reproduce replace the import import { Chart } from './charts/Chart'; with import { Chart } from '@tanstack/angular-charts';. The chart is deployed as an example as static file on GitHub Pages - https://elbe-ui.dev/labs.

ngAfterViewInit() {
this.adapter?.mount(this.surface.nativeElement)
}

ERROR TypeError: container.getBoundingClientRect is not a function
    at currentWidth (/Users/m/Dev/lab/elbe-ui/.angular/cache/22.0.8/elbeui/vite/deps_ssr/chunk-QA5GYM6C.js:1551:46)
    at createScene (/Users/m/Dev/lab/elbe-ui/.angular/cache/22.0.8/elbeui/vite/deps_ssr/chunk-QA5GYM6C.js:1776:19)
    at render (/Users/m/Dev/lab/elbe-ui/.angular/cache/22.0.8/elbeui/vite/deps_ssr/chunk-QA5GYM6C.js:1514:13)
    at mountChartRenderer (/Users/m/Dev/lab/elbe-ui/.angular/cache/22.0.8/elbeui/vite/deps_ssr/chunk-QA5GYM6C.js:1724:3)
    at Object.mount (/Users/m/Dev/lab/elbe-ui/.angular/cache/22.0.8/elbeui/vite/deps_ssr/chunk-RT53Y7UD.js:37:32)
    at _Chart.ngAfterViewInit (/Users/m/Dev/lab/elbe-ui/.angular/cache/22.0.8/elbeui/vite/deps_ssr/@tanstack_angular-charts.js:287:19)
    at callHookInternal (/Users/m/Dev/lab/elbe-ui/.angular/cache/22.0.8/elbeui/vite/deps_ssr/chunk-3VOHPZK5.js:4534:10)
    at callHook (/Users/m/Dev/lab/elbe-ui/.angular/cache/22.0.8/elbeui/vite/deps_ssr/chunk-3VOHPZK5.js:4549:7)
    at callHooks (/Users/m/Dev/lab/elbe-ui/.angular/cache/22.0.8/elbeui/vite/deps_ssr/chunk-3VOHPZK5.js:4523:9)
    at executeInitAndCheckHooks (/Users/m/Dev/lab/elbe-ui/.angular/cache/22.0.8/elbeui/vite/deps_ssr/chunk-3VOHPZK5.js:4492:5)

The error origin is occurring while trying to access container.getBoundingClientRect() on the server.

const currentWidth = () => {
const width = options.width ?? container.getBoundingClientRect().width
return options.width !== undefined || width > 0 ? width : undefined
}

When the chartOptions define a width another error is thrown due to SSR issues.

uncaughtException TypeError: container.replaceChildren is not a function
    at Object.destroy (/Users/m/Dev/lab/elbe-ui/.angular/cache/22.0.8/elbeui/vite/deps_ssr/chunk-QA5GYM6C.js:1769:17)
    at Object.destroy (/Users/m/Dev/lab/elbe-ui/.angular/cache/22.0.8/elbeui/vite/deps_ssr/chunk-RT53Y7UD.js:48:14)
    at _Chart.ngOnDestroy (/Users/m/Dev/lab/elbe-ui/.angular/cache/22.0.8/elbeui/vite/deps_ssr/@tanstack_angular-charts.js:290:19)
    at executeOnDestroys (/Users/m/Dev/lab/elbe-ui/.angular/cache/22.0.8/elbeui/vite/deps_ssr/chunk-3VOHPZK5.js:9095:20)
    at cleanUpView (/Users/m/Dev/lab/elbe-ui/.angular/cache/22.0.8/elbeui/vite/deps_ssr/chunk-3VOHPZK5.js:9012:5)
    at destroyViewTree (/Users/m/Dev/lab/elbe-ui/.angular/cache/22.0.8/elbeui/vite/deps_ssr/chunk-3VOHPZK5.js:8973:11)
    at destroyLView (/Users/m/Dev/lab/elbe-ui/.angular/cache/22.0.8/elbeui/vite/deps_ssr/chunk-3VOHPZK5.js:9001:3)
    at ViewRef.destroy (/Users/m/Dev/lab/elbe-ui/.angular/cache/22.0.8/elbeui/vite/deps_ssr/chunk-3VOHPZK5.js:10539:5)
    at eval (/Users/m/Dev/lab/elbe-ui/.angular/cache/22.0.8/elbeui/vite/deps_ssr/chunk-3VOHPZK5.js:17029:50)
    at Array.forEach (<anonymous>)

container.replaceChildren()


A solution is to call the this.adapter?.mount(this.surface.nativeElement) only in the browser using afterNextRender.
The SVG Chart is correctly rendered on the server and only mounts the chart in the browser.

constructor() {
  afterNextRender(() => {
      this.adapter?.mount(this.surface.nativeElement);
    });
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions