Edit history
After you edit fields, records, or views, open history to inspect earlier versions, compare changes, and restore a version when permitted. History reads server-persisted versions. Undo and redo apply to the current editing session and do not require a history service.
Prepare collaboration and history services
Complete collaboration integration and license configuration. Verify that two sessions can edit the same Bases document and that changes survive a reload.
Follow Office collaboration extensions and the History example to connect history storage and permissions. Core collaboration does not enable history automatically. The backend must also support history lists, version content, and restoration.
Add the history plugins
Add this to your existing product, license, and collaboration setup. If a preset or existing configuration already registers these plugins, update that configuration instead of registering them twice.
pnpm add @univerjs-pro/edit-history @univerjs-pro/edit-history-ui @univerjs-pro/bases-history @univerjs-pro/bases-history-uinpm install @univerjs-pro/edit-history @univerjs-pro/edit-history-ui @univerjs-pro/bases-history @univerjs-pro/bases-history-uiyarn add @univerjs-pro/edit-history @univerjs-pro/edit-history-ui @univerjs-pro/bases-history @univerjs-pro/bases-history-uibun add @univerjs-pro/edit-history @univerjs-pro/edit-history-ui @univerjs-pro/bases-history @univerjs-pro/bases-history-uiimport { UniverEditHistoryPlugin } from '@univerjs-pro/edit-history'import EditHistoryLocale from '@univerjs-pro/edit-history-ui/locale/en-US'import { UniverBasesHistoryPlugin } from '@univerjs-pro/bases-history'import { UniverBasesHistoryUIPlugin } from '@univerjs-pro/bases-history-ui'import HistoryLocale from '@univerjs-pro/bases-history-ui/locale/en-US'import { LocaleType, mergeLocales } from '@univerjs/core'import '@univerjs-pro/edit-history-ui/lib/index.css'import '@univerjs-pro/bases-history-ui/lib/index.css'const historyServerUrl = '/api/history'univerAPI.loadLocales(LocaleType.EN_US, mergeLocales(EditHistoryLocale, HistoryLocale))univer.registerPlugin(UniverEditHistoryPlugin, { historyServerUrl })univer.registerPlugin(UniverBasesHistoryPlugin)univer.registerPlugin(UniverBasesHistoryUIPlugin, { univerContainerId: 'app', historyServerUrl,})Replace /api/history with your application's history endpoint and ensure its API matches the client requests. Keep both historyServerUrl values identical. Set univerContainerId to the editor container's DOM ID, and load the locale that matches the editor.
The history viewer creates a separate read-only editor. For custom content, use viewerPlugins to add plugins that the viewer does not already include. Do not register built-in viewer plugins again.
View and restore versions
Open history from the editor menu and select a version to inspect its content and changes. Restoring changes the current shared document. Only users with restore permission should be able to do so, and the server must enforce that permission.
To verify the integration, edit fields, records, or views, wait for collaboration confirmation, and inspect the history list and version content. Reopen the application and restart the service to check persistence. Restore an earlier version and verify that another browser session receives the restored state.
If the list is empty, check whether history was recorded for this document, then check the document ID and service URL. If viewing works but restoration fails, check restore permissions and the collaboration connection. Reading history also requires authorization because older versions may contain data that has since been deleted.
Compare snapshots
To build a review screen or provide changes to an AI Agent, use compareUnitData() or prepare a comparison once with prepareUnitComparison(). Register the product History plugin and import the Facade entry. Supply two fully materialized snapshots of the same unit as beforeSnapshot and afterSnapshot; this read-only comparison does not require a history service and does not restore or merge content.
import { UnitComparisonDetailLevel, UnitComparisonFidelity } from '@univerjs-pro/edit-history'import { UniverInstanceType } from '@univerjs/core'import '@univerjs-pro/edit-history/facade'const comparison = univerAPI.prepareUnitComparison({ comparisonId: 'review-1', unitId: beforeSnapshot.id, type: UniverInstanceType.UNIVER_BASE, fidelity: UnitComparisonFidelity.SNAPSHOT, leftData: beforeSnapshot, rightData: afterSnapshot,})const overview = comparison.query({ detail: UnitComparisonDetailLevel.SUMMARY })const scope = overview.scopes[0]const page = comparison.query({ scope, offset: 0, limit: 100 })console.log(page.items, page.page.hasMore, page.diagnostics)Read scopes to discover available views, then pass a scope to query() to filter the result without rerunning the comparison. Results default to 100 items and accept up to 1,000 per page. Use page.hasMore with offset for additional items. summary describes the whole comparison, even when items are filtered. Check diagnostics.readiness and diagnostics.codes before treating the result as a complete comparison. For Node.js or CLI usage without an editor, see the headless comparison API.
How is this guide?