Atomic Angular — Doc interne

Preview Content

Render a document's converted preview in an iframe — with zoom, search-in-document, highlights, an AI-description toggle, and a Markdown fallback — from a single drop-in component.

<preview-content> is the whole document preview surface: it loads the previewed document, picks the right rendering path (a converted-document iframe, or a Markdown fallback when no conversion is available), and layers the toolbar (<preview-actions>) and page navigator (<preview-navigator>) on top.

Concept — conversion

A Sinequa index can store more than one rendered form of a document — its conversions (a PDF-like page image, a Markdown extraction, a multi-format bundle). <preview-content> resolves which conversion is active and swaps its whole rendering strategy (iframe vs. Markdown) based on it — this is not a cosmetic detail, the markdown branch skips the iframe and <preview-actions>'s search/highlights entirely.

Minimal example

A document preview panel
document-preview.component.ts
import { Component, input } from "@angular/core";
import { PreviewContentComponent } from "@sinequa/atomic-angular";
import type { Article, PreviewData } from "@sinequa/atomic";

@Component({
  selector: "document-preview",
  imports: [PreviewContentComponent],
  template: `<preview-content [article]="article()" (onLoadedData)="onLoaded($event)" class="h-full" />`,
})
export class DocumentPreviewComponent {
  readonly article = input<Article>();

  protected onLoaded(data: PreviewData | undefined) {
    console.log("Preview loaded:", data?.record?.title);
  }
}

Leave article unset to preview whatever the shared selection store currently holds — the common case when <preview-content> sits in a side panel or a route that reacts to document selection elsewhere on the page.

How it works

yes no valid invalid previewDataResource loads isMarkdown()? Render markdown pipe + local CSS zoom(no preview-actions, no iframe) previewValidationResource HEAD-checks the cached URL iframe + preview-actions + preview-navigator Preview unavailable

The iframe stays hidden behind a spinner overlay until it posts a ready message back (its own layout has settled) — only then does the component scroll it to the requested page and reveal it, so the user never sees the intermediate scroll jump. A current-page message keeps <preview-navigator> in sync as the user scrolls or pages manually inside the iframe.

Recipes

Hide search-in-document in a narrow host

showSearchActions reaches all the way down to <preview-actions>'s own showSearch input — set it once here rather than wrapping the nested component yourself.

A preview embedded in a resizable side panel
side-panel-preview.component.ts
import { Component, input } from "@angular/core";
import { PreviewContentComponent } from "@sinequa/atomic-angular";
import type { Article } from "@sinequa/atomic";

@Component({
  selector: "side-panel-preview",
  imports: [PreviewContentComponent],
  template: `<preview-content [article]="article()" [showSearchActions]="false" class="h-full" />`,
})
export class SidePanelPreviewComponent {
  readonly article = input<Article>();
}

Mirror the active conversion in a parent badge

onConversionSelect fires whenever the active conversion changes (including the very first auto-selection), so a parent can mirror it without owning any conversion state of its own.

A "primary format" badge next to the preview
preview-with-badge.component.ts
import { Component, input, signal } from "@angular/core";
import { PreviewContentComponent } from "@sinequa/atomic-angular";
import type { CConverter } from "@sinequa/atomic-angular";
import type { Article } from "@sinequa/atomic";

@Component({
  selector: "preview-with-badge",
  imports: [PreviewContentComponent],
  template: `
    @if (activeConverter(); as converter) {
      <span class="badge">{{ converter.display ?? converter.format }}</span>
    }
    <preview-content [article]="article()" (onConversionSelect)="activeConverter.set($event)" class="h-full" />
  `,
})
export class PreviewWithBadgeComponent {
  readonly article = input<Article>();
  protected readonly activeConverter = signal<CConverter | undefined>(undefined);
}

Options

Prop

Type

Outputs

Prop

Type

Pitfalls

What's next

On this page