Print Plugin
The Print Plugin enables printing the full grid content by temporarily disabling virtualization and applying print-optimized styles. It handles large datasets gracefully with configurable row limits.
Features
Section titled “Features”- Print Layout Mode - Optimized CSS styles for printing
- Page Orientation - Portrait or landscape orientation
- Row Limits - Configurable maximum rows with confirmation dialog for large datasets
- Toolbar Button - Optional print button in grid header
- Title & Timestamp - Optional print header with customizable title and timestamp
- Column Hiding - Mark columns as
printHiddento exclude from print output
Installation
Section titled “Installation”import '@toolbox-web/grid/features/print';Basic Usage
Section titled “Basic Usage”Use the controls to try different orientations, toggle title/timestamp, isolated printing, and the toolbar button.
Enable “Toolbar button” to add a print icon to the grid header (requires shell.header config).
import '@toolbox-web/grid';import { queryGrid } from '@toolbox-web/grid';import '@toolbox-web/grid/features/print';
const grid = queryGrid('tbw-grid')!;const btn = document.querySelector('#print-basic-btn');
const employeeData = [ { id: 1, name: 'Alice Johnson', department: 'Engineering', salary: 85000, status: 'Active', email: 'alice@company.com' }, { id: 2, name: 'Bob Smith', department: 'Marketing', salary: 72000, status: 'Active', email: 'bob@company.com' }, { id: 3, name: 'Carol Williams', department: 'Engineering', salary: 92000, status: 'Active', email: 'carol@company.com' }, { id: 4, name: 'David Brown', department: 'Sales', salary: 68000, status: 'On Leave', email: 'david@company.com' }, { id: 5, name: 'Emma Davis', department: 'HR', salary: 65000, status: 'Active', email: 'emma@company.com' }, { id: 6, name: 'Frank Miller', department: 'Engineering', salary: 88000, status: 'Active', email: 'frank@company.com' }, { id: 7, name: 'Grace Wilson', department: 'Marketing', salary: 75000, status: 'Active', email: 'grace@company.com' }, { id: 8, name: 'Henry Taylor', department: 'Sales', salary: 70000, status: 'Active', email: 'henry@company.com' }, { id: 9, name: 'Ivy Anderson', department: 'Finance', salary: 82000, status: 'On Leave', email: 'ivy@company.com' }, { id: 10, name: 'Jack Thomas', department: 'Engineering', salary: 95000, status: 'Active', email: 'jack@company.com' },];
let opts: Record<string, unknown> = { orientation: 'landscape', button: false, includeTitle: true, includeTimestamp: true, isolate: true,};
function applyConfig() { grid.gridConfig = { fitMode: 'stretch', ...(opts.button ? { shell: { header: { title: 'Employee Report' } } } : {}), columns: [ { field: 'id', header: 'ID', width: 60 }, { field: 'name', header: 'Name', minWidth: 150 }, { field: 'department', header: 'Department', width: 120 }, { field: 'email', header: 'Email', minWidth: 200 }, { field: 'salary', header: 'Salary', width: 100, align: 'right' }, { field: 'status', header: 'Status', width: 100 }, ], features: { print: { orientation: opts.orientation as string, button: opts.button as boolean, title: 'Employee Report', includeTitle: opts.includeTitle as boolean, includeTimestamp: opts.includeTimestamp as boolean, }, }, }; grid.rows = employeeData;}
applyConfig();
btn?.addEventListener('click', () => { const plugin = grid.getPluginByName('print'); plugin?.print({ isolate: opts.isolate as boolean });});<div style="margin-bottom: 12px;"> <button style="padding: 8px 16px; cursor: pointer;">🖨️ Print Grid</button></div><tbw-grid style="height: 400px;"></tbw-grid>import { queryGrid } from '@toolbox-web/grid';import '@toolbox-web/grid/features/print';
const grid = queryGrid('tbw-grid');
grid.gridConfig = { columns: [ { field: 'name', header: 'Name' }, { field: 'department', header: 'Department' }, { field: 'salary', header: 'Salary' }, ], features: { print: { title: 'Employee Report', includeTitle: true, includeTimestamp: true, }, },};
// Programmatic printconst plugin = grid.getPluginByName('print');await plugin.print();import '@toolbox-web/grid-react/features/print';import { DataGrid } from '@toolbox-web/grid-react';import { useGridPrint } from '@toolbox-web/grid-react/features/print';
function EmployeeGrid({ data }) { const { print } = useGridPrint();
const handlePrint = async () => { await print({ title: 'Employee Report' }); };
return ( <div> <button onClick={handlePrint}>Print Report</button> <DataGrid rows={data} columns={[ { field: 'name', header: 'Name' }, { field: 'department', header: 'Department' }, { field: 'salary', header: 'Salary' }, ]} print={{ title: 'Employee Report', includeTitle: true, includeTimestamp: true, }} style={{ height: '400px' }} /> </div> );}<script setup>import '@toolbox-web/grid-vue/features/print';import { TbwGrid, TbwGridColumn } from '@toolbox-web/grid-vue';import { ref } from 'vue';
const data = [ { name: 'Alice', department: 'Engineering', salary: 95000 }, { name: 'Bob', department: 'Marketing', salary: 75000 },];
const gridRef = ref(null);
const handlePrint = async () => { await gridRef.value?.gridElement?.getPluginByName('print')?.print();};</script>
<template> <div> <button @click="handlePrint">Print Report</button> <TbwGrid ref="gridRef" :rows="data" :print="{ title: 'Employee Report', includeTitle: true, includeTimestamp: true }" style="height: 400px"> <TbwGridColumn field="name" header="Name" /> <TbwGridColumn field="department" header="Department" /> <TbwGridColumn field="salary" header="Salary" /> </TbwGrid> </div></template>// Feature import - enables the [print] inputimport '@toolbox-web/grid-angular/features/print';
import { Component, viewChild, ElementRef } from '@angular/core';import { Grid } from '@toolbox-web/grid-angular';import type { ColumnConfig, GridElement } from '@toolbox-web/grid';
@Component({ selector: 'app-employee-grid', imports: [Grid], template: ` <button (click)="handlePrint()">Print Report</button> <tbw-grid #grid [rows]="rows" [columns]="columns" [print]="{ title: 'Employee Report', includeTitle: true, includeTimestamp: true }" style="height: 400px; display: block;"> </tbw-grid> `,})export class EmployeeGridComponent { gridRef = viewChild<ElementRef<GridElement>>('grid'); rows = [...];
columns: ColumnConfig[] = [ { field: 'name', header: 'Name' }, { field: 'department', header: 'Department' }, { field: 'salary', header: 'Salary' }, ];
async handlePrint() { const plugin = this.gridRef()?.nativeElement.getPluginByName('print'); await plugin?.print(); }}Configuration Options
Section titled “Configuration Options”See PrintConfig for the full list of options and defaults.
Hiding Columns in Print
Section titled “Hiding Columns in Print”Use the printHidden column property to exclude specific columns from print output.
This is useful for hiding action buttons, interactive elements, or columns that aren’t
relevant on paper.
import { queryGrid } from '@toolbox-web/grid';
const grid = queryGrid('tbw-grid');
grid.gridConfig = { columns: [ { field: 'id', header: 'ID' }, { field: 'name', header: 'Name' }, { field: 'email', header: 'Email' }, { field: 'actions', header: 'Actions', printHidden: true }, // Hidden when printing ], features: { print: true },};The printHidden property:
- Temporarily hides columns when
print()is called - Automatically restores column visibility after printing
- Preserves the original hidden state (if a column was already hidden, it stays hidden)
- Works independently of the VisibilityPlugin
import '@toolbox-web/grid';import { queryGrid } from '@toolbox-web/grid';import '@toolbox-web/grid/features/print';
const grid = queryGrid('tbw-grid');const btn = document.querySelector('#print-hidden-btn');
const employeeData = [ { id: 1, name: 'Alice Johnson', department: 'Engineering', salary: 85000, email: 'alice@company.com' }, { id: 2, name: 'Bob Smith', department: 'Marketing', salary: 72000, email: 'bob@company.com' }, { id: 3, name: 'Carol Williams', department: 'Engineering', salary: 92000, email: 'carol@company.com' }, { id: 4, name: 'David Brown', department: 'Sales', salary: 68000, email: 'david@company.com' }, { id: 5, name: 'Emma Davis', department: 'HR', salary: 65000, email: 'emma@company.com' }, { id: 6, name: 'Frank Miller', department: 'Engineering', salary: 88000, email: 'frank@company.com' }, { id: 7, name: 'Grace Wilson', department: 'Marketing', salary: 75000, email: 'grace@company.com' }, { id: 8, name: 'Henry Taylor', department: 'Sales', salary: 70000, email: 'henry@company.com' },];
grid.gridConfig = { fitMode: 'stretch', columns: [ { field: 'id', header: 'ID', width: 60 }, { field: 'name', header: 'Name', minWidth: 150 }, { field: 'department', header: 'Department', width: 120 }, { field: 'email', header: 'Email', minWidth: 200 }, { field: 'salary', header: 'Salary', width: 100, align: 'right' }, { field: 'actions', header: 'Actions', width: 100, printHidden: true, renderer: () => { const btn = document.createElement('button'); btn.textContent = 'Edit'; btn.style.cssText = 'padding: 4px 8px; cursor: pointer;'; return btn; }, }, ], features: { print: { title: 'Employee Report (Filtered)', includeTitle: true, includeTimestamp: true, }, },};grid.rows = employeeData;
btn?.addEventListener('click', () => { const plugin = grid.getPluginByName('print'); plugin?.print({ isolate: true });});<div style="margin-bottom: 12px;"> <button style="padding: 8px 16px; cursor: pointer;">🖨️ Print Grid</button> <span style="margin-left: 12px; font-size: 0.85rem; color: var(--sl-color-gray-3);"> The "Actions" column has <code>printHidden: true</code> and will not appear in the printout. </span></div><tbw-grid style="height: 400px;"></tbw-grid>Row Limits
Section titled “Row Limits”Two separate options control large dataset behavior:
warnThreshold- Shows a confirmation dialog when row count exceeds this value, letting users consent to a potentially slow print operationmaxRows- Hard-limits the printed rows to this number (excess rows are not rendered)
warnThreshold: 500 (shows
confirmation dialog) and maxRows: 100 (hard limit). Check the print preview to see only 100 rows.
// Warn at 500+ rows, but print all if confirmedfeatures: { print: { warnThreshold: 500 } }
// Hard limit to 100 rows (no warning, just limits)features: { print: { maxRows: 100, warnThreshold: 0 } }
// Warn at 500+ rows AND hard limit to 1000features: { print: { warnThreshold: 500, maxRows: 1000 } }The confirmation dialog shows:
- Total row count
- Note about hard limit (if
maxRowsis set) - Option to proceed or cancel
Events
Section titled “Events”The plugin emits events during the print lifecycle:
print-start
Section titled “print-start”Fired when print preparation begins:
grid.on('print-start', ({ rowCount, limitApplied, originalRowCount }) => { console.log('Preparing rows:', rowCount); console.log('Limit applied:', limitApplied); if (limitApplied) { console.log('Original count:', originalRowCount); }});print-complete
Section titled “print-complete”Fired when the print dialog closes:
grid.on('print-complete', ({ duration, rowCount }) => { console.log('Dialog open for:', duration, 'ms'); console.log('Rows prepared:', rowCount);});Programmatic API
Section titled “Programmatic API”print(params?)
Section titled “print(params?)”Initiates the print process. Returns a Promise that resolves when printing completes.
const plugin = grid.getPluginByName('print');
// Basic print (prints entire page)await plugin.print();
// With runtime overridesawait plugin.print({ title: 'Custom Report Title', orientation: 'portrait',});
// Isolated print - opens new window with only the gridawait plugin.print({ isolate: true });Print Parameters
Section titled “Print Parameters”| Parameter | Type | Description |
|---|---|---|
orientation | 'portrait' | 'landscape' | Override page orientation |
title | string | Override print title |
maxRows | number | Override maximum rows |
isolate | boolean | Print with page isolation (hides all non-grid content) |
Isolated Printing
Section titled “Isolated Printing”When isolate: true is passed, the plugin uses CSS to hide everything on the page
except the grid during printing. This is useful when:
- The page has navigation, sidebars, or headers that shouldn’t appear in print
- You want to print only the grid without surrounding UI
- The grid is embedded in an application framework like Storybook, Angular, etc.
// Print just the grid, hiding all other page contentawait plugin.print({ isolate: true });How it works:
- A temporary
@media printstylesheet is injected - The stylesheet hides all elements except the grid (identified by its unique ID)
- After printing, the stylesheet is removed
- The grid stays in place with virtualization disabled, so ALL rows are printed
isPrinting()
Section titled “isPrinting()”Returns true if a print operation is currently in progress.
if (plugin.isPrinting()) { console.log('Print already in progress');}Print CSS Classes
Section titled “Print CSS Classes”The plugin applies these CSS classes during printing:
| Class | Description |
|---|---|
.print-portrait | Applied when orientation is portrait |
.print-landscape | Applied when orientation is landscape |
.tbw-print-header | Print header container |
.tbw-print-header-title | Title element |
.tbw-print-header-timestamp | Timestamp element |
Custom Print Styles
Section titled “Custom Print Styles”Override print styles using CSS:
@media print { tbw-grid.print-landscape { /* Custom print styles */ font-size: 10pt; }
tbw-grid.print-landscape .dg-cell { border-color: #000; }}How It Works
Section titled “How It Works”- Disable Virtualization - Temporarily renders all rows (up to
maxRows) - Apply Print Styles - Adds print-mode CSS class and orientation class
- Add Print Header - Inserts title and timestamp (if configured)
- Trigger Print - Calls
window.print() - Cleanup - Restores virtualization and removes temporary elements
Browser Support
Section titled “Browser Support”The Print Plugin uses standard browser printing APIs (window.print(), @media print)
and works in all modern browsers:
- Chrome / Edge (Chromium)
- Firefox
- Safari
Best Practices
Section titled “Best Practices”- Set reasonable
maxRows- Consider limiting to ~5000 rows to prevent browser hangs - Use landscape for wide grids - More columns fit horizontally
- Test print preview - Use browser’s print preview to verify layout
- Custom titles - Provide meaningful titles for printed reports
- Use
printHiddenfor interactive columns - Hide action buttons, checkboxes, etc. - Use
isolate: true- When other page content interferes with print layout
Standalone Utility Function
Section titled “Standalone Utility Function”For simple use cases where you don’t need the full plugin, use the standalone
printGridIsolated function:
import { queryGrid } from '@toolbox-web/grid';import { printGridIsolated } from '@toolbox-web/grid/plugins/print';
const grid = queryGrid('tbw-grid');await printGridIsolated(grid, { orientation: 'landscape',});This function injects a temporary CSS stylesheet that hides everything except
the target grid during printing. The grid must have an id attribute (DataGridElement
auto-generates one if not explicitly set).
Note: Unlike the PrintPlugin, this function does NOT disable virtualization.
If you need to print all rows, use the full PrintPlugin with isolate: true.