Render · API Reference

provideRender()

Registers global default configuration for @threadplane/render via Angular's dependency injection system.

Import

import { provideRender, RENDER_CONFIG } from '@threadplane/render';

Signature

function provideRender(config: RenderConfig): EnvironmentProviders;

Parameters

ParameterTypeDescription
configRenderConfigConfiguration object with default registry, store, functions, and handlers

Returns

EnvironmentProviders -- suitable for use in ApplicationConfig.providers or bootstrapApplication().

RenderConfig

interface RenderConfig {
  registry?: AngularRegistry;
  store?: StateStore;
  functions?: Record<string, ComputedFunction>;
  handlers?: Record<string, (params: Record<string, unknown>) => unknown | Promise<unknown>>;
}
PropertyTypeDescription
registryAngularRegistryDefault component registry for all <render-spec> instances
storeStateStoreDefault state store for all <render-spec> instances
functionsRecord<string, ComputedFunction>Default computed functions for $computed prop expressions
handlersRecord<string, Handler>Default event handlers for action dispatch

All properties are optional. Only provide the defaults you need.

RENDER_CONFIG Token

The configuration is stored in the RENDER_CONFIG injection token:

import { InjectionToken } from '@angular/core';
 
const RENDER_CONFIG = new InjectionToken<RenderConfig>('RENDER_CONFIG');

You can inject it directly if needed:

import { inject } from '@angular/core';
import { RENDER_CONFIG } from '@threadplane/render';
 
const config = inject(RENDER_CONFIG, { optional: true });
// null if provideRender() was not called

Usage

Basic Setup

// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRender, defineAngularRegistry } from '@threadplane/render';
import { TextComponent } from './components/text.component';
import { CardComponent } from './components/card.component';
 
export const appConfig: ApplicationConfig = {
  providers: [
    provideRender({
      registry: defineAngularRegistry({
        Text: TextComponent,
        Card: CardComponent,
      }),
    }),
  ],
};

With Store and Handlers

import {
  provideRender,
  defineAngularRegistry,
  signalStateStore,
} from '@threadplane/render';
 
const globalStore = signalStateStore({ theme: 'light' });
 
export const appConfig: ApplicationConfig = {
  providers: [
    provideRender({
      registry: defineAngularRegistry({
        Text: TextComponent,
        Card: CardComponent,
      }),
      store: globalStore,
      functions: {
        uppercase: (args: Record<string, unknown>) =>
          String(args['text']).toUpperCase(),
      },
      handlers: {
        toggleTheme: () => {
          const current = globalStore.get('/theme');
          globalStore.set('/theme', current === 'light' ? 'dark' : 'light');
        },
      },
    }),
  ],
};

Registry Only

If you only need a global registry and want to provide stores per-instance:

provideRender({
  registry: defineAngularRegistry({
    Text: TextComponent,
    Card: CardComponent,
    Button: ButtonComponent,
  }),
})

Resolution Priority

RenderSpecComponent resolves each configuration value using this priority:

PrioritySourceDescription
1 (highest)Component input[registry], [store], [functions], [handlers] on <render-spec>
2RENDER_CONFIGGlobal defaults from provideRender()
3 (lowest)Internal fallbackEmpty registry, internal signalStateStore() from spec.state

This means inputs always win over global config:

// Global config
provideRender({ registry: registryA, store: storeA });
 
// In template -- registryB overrides registryA, but storeA is still used
<render-spec [spec]="spec" [registry]="registryB" />

Global vs Component-Level Config

Use provideRender() when you want shared defaults across your entire application:

// All <render-spec> instances use this registry by default
provideRender({ registry: myRegistry })

This is ideal when you have a single component library that all specs should use.

Optional Provider

provideRender() is not required. If you skip it, RenderSpecComponent requires you to pass registry and store as inputs (or relies on the internal store fallback).

<!-- Works without provideRender() -- all config via inputs -->
<render-spec [spec]="spec" [registry]="registry" [store]="store" />
provideRenderfunction

Bootstrap `@threadplane/render` in an Angular application or standalone component tree. Registers the shared RenderConfig token and the internal `RenderLifecycleService` that coordinates mount/unmount events across dynamically rendered components. Call this once alongside `provideChat` in `bootstrapApplication` (or the root `ApplicationConfig`).

provideRender(config: RenderConfig): EnvironmentProviders

Parameters

ParameterTypeDescription
configRenderConfigOptions bag that controls the render feature set: - `registry` — component registry returned by defineAngularRegistry; maps tool-call names to Angular components. - `store` — optional `StateStore` for `\@json-render/core` state binding. - `functions` — optional map of computed functions available inside specs. - `handlers` — optional map of event handlers triggered by spec actions.

Returns

EnvironmentProviders

Examples

// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { defineAngularRegistry, provideRender } from '@threadplane/render';
import { provideChat } from '@threadplane/chat';
import { DayCardComponent } from './day-card.component';

const registry = defineAngularRegistry({ day_card: DayCardComponent });

bootstrapApplication(AppComponent, {
  providers: [
    provideRender({ registry }),
    provideChat({ renderRegistry: registry }),
  ],
});