libs/core/src/lib/services/taly-content-render.service.ts

Description

Bridges page content render-readiness to the frame so it paints the surrounding sections (footer, actions, small print) only once content has rendered, avoiding Cumulative Layout Shift (CLS).

Several Building Block pages can be alive at the same time — the routed page plus the projected frame-header-actions and frame-global-sidebar-content pages — so readiness is tracked per source and only reported as ready once every registered source is ready.

Provided by FrameComponent, so the frame and the Building Block pages projected into it (routed page, header-actions, global-sidebar) resolve the same instance via the element injector. Pages rendered outside a frame inject it optionally and simply skip reporting.

Relationships

Used by

Depends on

No results matching.

Index

Properties
Methods

Methods

registerSource
registerSource()

Register a content source. It starts as not-ready, so registering holds back the frame until the source reports otherwise. Returns a key used to update or remove it.

setSourceReady
setSourceReady(key: ContentRenderSourceKey, ready: boolean)
Parameters :
Name Type Optional
key ContentRenderSourceKey No
ready boolean No
Returns : void
unregisterSource
unregisterSource(key: ContentRenderSourceKey)
Parameters :
Name Type Optional
key ContentRenderSourceKey No
Returns : void

Properties

contentRenderReady$
Type : unknown
Default value : this._contentRenderReady$.pipe(distinctUntilChanged())
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators';

export type ContentRenderSourceKey = symbol;

/**
 * Bridges page content render-readiness to the frame so it paints the surrounding sections
 * (footer, actions, small print) only once content has rendered, avoiding Cumulative Layout
 * Shift (CLS).
 *
 * Several Building Block pages can be alive at the same time — the routed page plus the
 * projected `frame-header-actions` and `frame-global-sidebar-content` pages — so readiness
 * is tracked per source and only reported as ready once every registered source is ready.
 *
 * Provided by `FrameComponent`, so the frame and the Building Block pages projected into it
 * (routed page, header-actions, global-sidebar) resolve the same instance via the element
 * injector. Pages rendered outside a frame inject it optionally and simply skip reporting.
 */
@Injectable()
export class TalyContentRenderService {
  private _sourceReadiness = new Map<ContentRenderSourceKey, boolean>();
  private _contentRenderReady$ = new BehaviorSubject<boolean>(true);

  contentRenderReady$ = this._contentRenderReady$.pipe(distinctUntilChanged());

  /**
   * Register a content source. It starts as not-ready, so registering holds back the frame
   * until the source reports otherwise. Returns a key used to update or remove it.
   */
  registerSource(): ContentRenderSourceKey {
    const key = Symbol('content-render-source');
    this._sourceReadiness.set(key, false);
    this._emitReadiness();
    return key;
  }

  setSourceReady(key: ContentRenderSourceKey, ready: boolean): void {
    if (!this._sourceReadiness.has(key)) {
      return;
    }
    this._sourceReadiness.set(key, ready);
    this._emitReadiness();
  }

  unregisterSource(key: ContentRenderSourceKey): void {
    if (this._sourceReadiness.delete(key)) {
      this._emitReadiness();
    }
  }

  private _emitReadiness(): void {
    const allReady = Array.from(this._sourceReadiness.values()).every(Boolean);
    this._contentRenderReady$.next(allReady);
  }
}

results matching ""

    No results matching ""