Rasterex APINPM Package/docs/components/files/page-list

Page List

Listen for pageList and selectPage commands to build custom host-side page lists and thumbnail rails.

Overview

The SDK exposes page list metadata and active selection updates from the Canvas session.

Use the pageList and pageChanged event streams as the single source of truth for rendering custom page rails, thumbnail grids, or PDF navigation panels.

  • Instant Syncing: Receive list arrays containing selection flags and thumbnail URLs dynamically.
  • Flexible Navigation: Route viewport focuses by calling .selectPage() with indices or human-facing page numbers.
  • Embedded Thumbnails: Read base64 thumbnailDataUrl references directly from the payload (no separate file retrieval needed).

Quick Start

Listen to page notifications and route viewport selections programmatically:

Subscribe to pageList updates

const stopPageList = viewer.documents.on("pageList", (event) => {
  console.log("Current page index:", event.currentPage);
  console.log("Total page count:", event.pageCount);
});

Select a page

// Select by 0-based index
viewer.documents.selectPage({ pageIndex: 2 });

// Select by human-facing page number (1-based)
viewer.documents.selectPage({ pageNumber: 3 });

Payload Shape

The pageList payload shape is structured as follows:

type CanvasPageListPayload = {
  activeId: string;
  currentPage: number;
  pageCount: number;
  pages: Array<{
    index: number; // 0-based page index
    pageNumber: number; // 1-based page number
    label: string; // Display label (e.g. "Page 1")
    isSelected: boolean; // Active selection indicator
    thumbnailDataUrl?: string; // Optional base64 preview string
    thumbnailWidth?: number;
    thumbnailHeight?: number;
  }>;
};
Payload Shape

Host Guidance

When integrating custom page lists, align workflows with these rules:

  • One Source of Truth: Keep viewport navigation state in the canvas. Render selection outlines based on page.isSelected elements rather than updating parent flags directly on click.
  • Thumbnail Fallbacks: The base64 thumbnailDataUrl string is generated asynchronously. Provide a loader icon or colored placeholder while the preview loads.

Vanilla Integration

Copy these project setup files to configure mounting, page event subscriptions, and page selection handlers:

import { createViewer } from "@rasterex/viewer";
import "./style.css";

const viewer = createViewer({
  container: "#viewer"
});

const pagesEl = document.querySelector("#pages-container");

function renderPages(event) {
  if (!pagesEl) return;
  pagesEl.innerHTML = "";

  event.pages.forEach((page) => {
    const button = document.createElement("button");
    button.type = "button";
    button.className = "page-item";
    button.setAttribute("aria-pressed", String(page.isSelected));

    if (page.thumbnailDataUrl) {
      const img = document.createElement("img");
      img.src = page.thumbnailDataUrl;
      img.width = 60;
      button.appendChild(img);
    }

    const label = document.createElement("span");
    label.textContent = page.label;
    button.appendChild(label);

    button.addEventListener("click", () => {
      viewer.documents.selectPage({ pageIndex: page.index });
    });

    pagesEl.appendChild(button);
  });
}

async function startViewer() {
  await viewer.mount();
  await viewer.ready();

  viewer.documents.on("pageList", renderPages);

  await viewer.documents.open({
    url: "https://pdfobject.com/pdf/sample.pdf",
    displayName: "sample.pdf"
  });
}

startViewer().catch(console.error);
Vanilla Integration

React Integration

Subscribe to pages arrays and select views using standard React state hooks:

import { useEffect, useRef, useState } from "react";
import { createViewer, type CanvasPageListItem, type RasterexViewer } from "@rasterex/viewer";
import "./style.css";

export function FilePagesExample() {
  const containerRef = useRef<HTMLDivElement | null>(null);
  const viewerRef = useRef<RasterexViewer | null>(null);
  const [pages, setPages] = useState<CanvasPageListItem[]>([]);
  const [currentPage, setCurrentPage] = useState(0);

  useEffect(() => {
    if (!containerRef.current) return undefined;

    const viewer = createViewer({ container: containerRef.current });
    viewerRef.current = viewer;

    const unsubscribe = viewer.documents.on("pageList", (event) => {
      setPages(event.pages);
      setCurrentPage(event.currentPage);
    });

    async function start(): Promise<void> {
      await viewer.mount();
      await viewer.ready();

      await viewer.documents.open({
        url: "https://pdfobject.com/pdf/sample.pdf",
        displayName: "sample.pdf"
      });
    }

    void start().catch(console.error);

    return () => {
      unsubscribe();
      viewer.destroy();
      viewerRef.current = null;
    };
  }, []);

  function selectPage(page: CanvasPageListItem): void {
    viewerRef.current?.documents.selectPage({ pageIndex: page.index });
  }

  return (
    <div className="layout">
      <aside id="pages-container">
        {pages.map((page) => (
          <button
            key={page.index}
            type="button"
            className="page-item"
            aria-pressed={page.index === currentPage}
            onClick={() => selectPage(page)}
          >
            {page.thumbnailDataUrl && (
              <img src={page.thumbnailDataUrl} alt={page.label} width={60} />
            )}
            <span>{page.label}</span>
          </button>
        ))}
      </aside>
      <div ref={containerRef} style={{ height: 600 }} />
    </div>
  );
}
React Integration

Vue Integration

Subscribe to pages arrays and select views using standard Vue Composition reactive variables:

<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref, shallowRef } from "vue";
import { createViewer, type CanvasPageListItem, type RasterexViewer } from "@rasterex/viewer";
import "./style.css";

const containerRef = ref<HTMLElement | null>(null);
const viewerRef = shallowRef<RasterexViewer | null>(null);
const pages = ref<CanvasPageListItem[]>([]);
const currentPage = ref(0);

let unsubscribe: (() => void) | undefined;

onMounted(async () => {
  if (!containerRef.value) return;

  const viewer = createViewer({ container: containerRef.value });
  viewerRef.value = viewer;

  unsubscribe = viewer.documents.on("pageList", (event) => {
    pages.value = event.pages;
    currentPage.value = event.currentPage;
  });

  try {
    await viewer.mount();
    await viewer.ready();

    await viewer.documents.open({
      url: "https://pdfobject.com/pdf/sample.pdf",
      displayName: "sample.pdf"
    });
  } catch (error) {
    console.error(error);
  }
});

onBeforeUnmount(() => {
  unsubscribe?.();
  viewerRef.value?.destroy();
  viewerRef.value = null;
});

function selectPage(page: CanvasPageListItem) {
  viewerRef.value?.documents.selectPage({ pageIndex: page.index });
}
</script>

<template>
  <div class="layout">
    <aside id="pages-container">
      <button
        v-for="page in pages"
        :key="page.index"
        type="button"
        class="page-item"
        :aria-pressed="page.index === currentPage"
        @click="selectPage(page)"
      >
        <img v-if="page.thumbnailDataUrl" :src="page.thumbnailDataUrl" alt="Thumbnail" width="60" />
        <span>{{ page.label }}</span>
      </button>
    </aside>
    <div ref="containerRef" style="height: 600px" />
  </div>
</template>
Vue Integration

Angular Integration

Subscribe to pages arrays and select views inside an Angular component model:

import {
  AfterViewInit,
  Component,
  ElementRef,
  OnDestroy,
  ViewChild
} from "@angular/core";
import { createViewer, type CanvasPageListItem, type RasterexViewer } from "@rasterex/viewer";

@Component({
  selector: "app-file-pages",
  templateUrl: "./file-pages.component.html"
})
export class FilePagesComponent implements AfterViewInit, OnDestroy {
  @ViewChild("viewerContainer", { static: true })
  viewerContainer!: ElementRef<HTMLElement>;

  pages: CanvasPageListItem[] = [];
  currentPage = 0;

  private viewer: RasterexViewer | null = null;
  private unsubscribe?: () => void;

  async ngAfterViewInit(): Promise<void> {
    const viewer = createViewer({
      container: this.viewerContainer.nativeElement
    });

    this.viewer = viewer;

    this.unsubscribe = viewer.documents.on("pageList", (event) => {
      this.pages = event.pages;
      this.currentPage = event.currentPage;
    });

    try {
      await viewer.mount();
      await viewer.ready();

      await viewer.documents.open({
        url: "https://pdfobject.com/pdf/sample.pdf",
        displayName: "sample.pdf"
      });
    } catch (error) {
      console.error(error);
    }
  }

  selectPage(page: CanvasPageListItem): void {
    this.viewer?.documents.selectPage({ pageIndex: page.index });
  }

  ngOnDestroy(): void {
    this.unsubscribe?.();
    this.viewer?.destroy();
  }
}
Angular Integration

Live Preview

Open the focused demo to watch the page rail update live from pageList events.

File Page List Demo

Focused live demo for the pageList workflow.

Preview opens in a large modal for zoom-friendly review.