Skip to content

Angular Integration

The @witqq/spreadsheet-angular package provides WitTableComponent, a standalone Angular component that wraps the core canvas engine with Angular-native inputs, outputs, and a public API accessible via ViewChild.

Terminal window
npm install @witqq/spreadsheet @witqq/spreadsheet-angular

Requires Angular 16+ (standalone component support).

import { Component } from '@angular/core';
import { WitTableComponent } from '@witqq/spreadsheet-angular';
import type { ColumnDef } from '@witqq/spreadsheet';
@Component({
selector: 'app-root',
standalone: true,
imports: [WitTableComponent],
template: `
<witqq spreadsheet
[columns]="columns"
[data]="data"
(cellChange)="onCellChange($event)"
/>
`,
})
export class AppComponent {
columns: ColumnDef[] = [
{ key: 'name', title: 'Name', width: 180 },
{ key: 'email', title: 'Email', width: 220 },
];
data = [
{ name: 'Alice', email: 'alice@example.com' },
{ name: 'Bob', email: 'bob@example.com' },
];
onCellChange(event: any) {
console.log('Cell changed:', event);
}
}

The component selector is witqq spreadsheet. As a standalone component, import it directly into your component’s imports array — no NgModule required.

All inputs map to WitEngineConfig fields:

InputTypeRequiredDescription
columnsColumnDef[]YesColumn definitions
dataRecord<string, unknown>[]NoRow data array
rowCountnumberNoTotal row count (virtual scrolling)
themeWitThemeNoTheme object
frozenRowsnumberNoNumber of frozen rows
frozenColumnsnumberNoNumber of frozen columns
editablebooleanNoEnable cell editing
sortablebooleanNoEnable column sorting
showGridLinesbooleanNoShow grid lines
showRowNumbersbooleanNoShow row numbers
rowHeightnumberNoDefault row height (px)
headerHeightnumberNoHeader row height (px)
widthnumber | stringNoContainer width
heightnumber | stringNoContainer height
<witqq spreadsheet
[columns]="columns"
[data]="data"
(cellChange)="onCellChange($event)"
(selectionChange)="onSelectionChange($event)"
(sortChange)="onSortChange($event)"
(filterChange)="onFilterChange($event)"
(scroll)="onScroll($event)"
(ready)="onReady()"
/>
OutputPayloadFires when
cellChangeCellChangeEventA cell value is edited
selectionChangeSelectionChangeEventActive cell or selection range changes
sortChangeSortChangeEventColumn sort is applied or cleared
filterChangeFilterChangeEventFilter is applied, changed, or removed
scrollScrollEventThe viewport scrolls
readyvoidThe engine is fully initialized

Access the component’s public methods via @ViewChild:

import { Component, ViewChild } from '@angular/core';
import { WitTableComponent } from '@witqq/spreadsheet-angular';
@Component({
selector: 'app-root',
standalone: true,
imports: [WitTableComponent],
template: `
<witqq-spreadsheet #table [columns]="columns" [data]="data" />
<button (click)="undo()">Undo</button>
<button (click)="redo()">Redo</button>
<button (click)="table.print()">Print</button>
`,
})
export class AppComponent {
@ViewChild('table') table!: WitTableComponent;
columns = [/* ... */];
data = [/* ... */];
undo() { this.table.undo(); }
redo() { this.table.redo(); }
}
MethodDescription
getInstance()Access the underlying WitEngine
focus()Focus the table container
getSelection()Current selection state
selectCell(row, col)Programmatically select a cell
getCell(row, col)Read cell data
setCell(row, col, value)Write a cell value
undo() / redo()Command history navigation
scrollTo(x, y)Scroll to pixel position
requestRender()Force a canvas re-render
installPlugin(plugin)Install a plugin at runtime
removePlugin(name)Remove a plugin by name
print()Trigger print layout

The component implements OnChanges and reacts to two input changes:

  • theme — calls engine.setTheme() when the theme input changes (skips first change)
  • data — clears the cell store, bulk-loads the new data, updates row count, and re-renders (skips first change since ngOnInit handles initial setup)
@Component({
template: `<witqq-spreadsheet [columns]="columns" [data]="rows" [theme]="theme" />`,
})
export class AppComponent {
theme = lightTheme;
rows = initialData;
toggleTheme() {
this.theme = this.theme === lightTheme ? darkTheme : lightTheme;
}
updateData(newRows: Record<string, unknown>[]) {
this.rows = newRows; // triggers ngOnChanges → bulk reload
}
}
HookBehavior
ngOnInitCreates WitEngine, mounts to container, subscribes to events
ngOnChangesUpdates theme and data when inputs change
ngOnDestroyUnsubscribes events, calls engine.destroy(), nullifies reference
import { Component, ViewChild, AfterViewInit, OnDestroy } from '@angular/core';
import { WitTableComponent } from '@witqq/spreadsheet-angular';
import { FormulaPlugin, ExcelPlugin } from '@witqq/spreadsheet-plugins';
@Component({
selector: 'app-root',
standalone: true,
imports: [WitTableComponent],
template: `<witqq-spreadsheet #table [columns]="columns" [data]="data" />`,
})
export class AppComponent implements AfterViewInit, OnDestroy {
@ViewChild('table') table!: WitTableComponent;
ngAfterViewInit() {
this.table.installPlugin(new FormulaPlugin());
this.table.installPlugin(new ExcelPlugin());
}
ngOnDestroy() {
this.table.removePlugin('formula');
this.table.removePlugin('excel');
}
}

Import types from @witqq/spreadsheet:

import type {
ColumnDef,
CellData,
CellValue,
Selection,
WitTheme,
WitPlugin,
CellChangeEvent,
SelectionChangeEvent,
SortChangeEvent,
FilterChangeEvent,
ScrollEvent,
} from '@witqq/spreadsheet';