원클릭으로
creating-docs-examples
// Use when creating code examples for documentation pages - JavaScript, TypeScript, React, Angular, and Vue variants with proper imports, registration, and license key
// Use when creating code examples for documentation pages - JavaScript, TypeScript, React, Angular, and Vue variants with proper imports, registration, and license key
| name | creating-docs-examples |
| path | docs/** |
| description | Use when creating code examples for documentation pages - JavaScript, TypeScript, React, Angular, and Vue variants with proper imports, registration, and license key |
This skill covers how to write runnable code examples that are embedded in documentation guide pages.
Each guide has framework-specific subdirectories for its examples:
docs/content/guides/category/feature/
feature.md # The guide page
javascript/ # JS examples
example1.js # Generated from TS - do not edit directly
example1.ts # Primary source - edit this first
react/ # React variants
example1.jsx # Generated from TSX
example1.tsx # Primary source
angular/ # Angular variants
example1.ts
example1.html # Template file
vue/ # Vue 3 variants
example1.js
example1.html # Template file
example1 = basic setup, example2 = a configuration variation, example3 = advanced usage..ts / .tsx file first. From docs/, generate the JS variant with: npm run docs:code-examples:generate-js -- <path-to-ts-file> (path relative to docs/). Never hand-edit generated JS files.createSpreadsheetData() or domain-appropriate sample data (product names, dates, currencies). Avoid trivial arrays like [1, 2, 3].Imports - use the base import and explicit registration:
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
registerAllModules();
For examples that demonstrate tree-shaking, import individual plugins and cell types instead of registerAllModules().
License key - always include:
licenseKey: 'non-commercial-and-evaluation'
Container element - target the conventional #example div:
const container = document.querySelector('#example');
React (TSX/JSX):
import { HotTable } from '@handsontable/react-wrapper';
import { registerAllModules } from 'handsontable/registry';
registerAllModules();
const App = () => {
return <HotTable data={data} licenseKey="non-commercial-and-evaluation" />;
};
Angular:
standalone: true, imports: [HotTableModule]).app.config.ts (not app.module.ts) with ApplicationConfig, provideZoneChangeDetection({ eventCoalescing: true }), and global HOT_GLOBAL_CONFIG for the license key.licenseKey to individual <hot-table> bindings -- it is set globally in app.config.ts.@if / @for (x of list; track x.id) -- never *ngIf / *ngFor.AppComponent in every example.Critical Angular JIT restrictions — the docs site bootstraps Angular examples with JIT in the browser. JIT cannot load external files at runtime:
styleUrls in standalone components. CSS is injected globally by the example-runner via the --css slot. If you need component-scoped styles, use inline styles: ['...'].templateUrl. Always define the component's template inline with template: \...`. The angular/example1.html` file is the outer wrapper (selector tag) consumed by the example-runner -- it is not the component's template.inject() instead. JIT mode lacks TypeScript decorator metadata, so constructor DI throws NG0202.(afterInit)="handler()"). Put hook functions inside gridSettings instead.RowObject, ViewChild, NgFor) can cause module resolution errors.The .ts file contains both app.component.ts and app.config.ts as separate /* file: ... */ sections within a single file:
/* file: app.component.ts */
import { Component } from '@angular/core';
import { GridSettings, HotTableModule } from '@handsontable/angular-wrapper';
@Component({
standalone: true,
imports: [HotTableModule],
selector: 'example1-feature-name',
template: `
<div>
<hot-table [data]="data" [settings]="gridSettings"></hot-table>
</div>
`,
})
export class AppComponent {
readonly data = [...];
readonly gridSettings: GridSettings = { ... };
}
/* end-file */
/* file: app.config.ts */
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { registerAllModules } from 'handsontable/registry';
import { HOT_GLOBAL_CONFIG, HotGlobalConfig, NON_COMMERCIAL_LICENSE } from '@handsontable/angular-wrapper';
registerAllModules();
export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
{ provide: HOT_GLOBAL_CONFIG, useValue: { license: NON_COMMERCIAL_LICENSE } as HotGlobalConfig },
],
};
/* end-file */
The angular/example1.html file is the outer wrapper (not the component template):
<div>
<example1-feature-name></example1-feature-name>
</div>
Edit on StackBlitz: When you use Edit on StackBlitz, docs/public/example-tabs.js merges each framework's companion example*.html into the generated app shell. parseDocsExampleHtmlForStackBlitz uses the browser DOMParser to collect style nodes for <head> and drop script nodes from the body fragment. mergeCompanionHtmlForStackBlitz wires that into the StackBlitz template. Examples with no HTML tab keep the previous default mount markup.
See skill angular-wrapper-dev for the full reference.
Vue 3:
.js file..html file using <hot-table>.After creating example files, embed them in the guide's .md file using the @[code] directive inside an ::: example container. See the writing-docs-pages skill for the full embedding syntax.
licenseKey: 'non-commercial-and-evaluation' present.handsontable/base + registration pattern.Use when writing or modifying Jasmine/Puppeteer E2E tests (*.spec.js) for Handsontable, or when a bug fix or feature change needs E2E test coverage. Covers standard boilerplate, async/await rules, global helpers, event simulation, plugin lifecycle patterns, and writing theme-agnostic assertions that pass under all themes without branching on theme name.
Use when creating a demo or test page for manual testing of Handsontable. Trigger when the user asks to create a demo, test page, repro page, reproduction case, manual test, or wants to verify a bug fix or feature visually. Also trigger when the user mentions dev-generated.html, dev-pr.html, dev-latest.html, dev.html, or wants to compare behavior between a released version and a local build. Use this for any PR that needs a manual testing artifact.
Use when working with Handsontable themes, CSS custom properties, SCSS files, theme tokens, or visual styling - covers theme architecture, CSS variable API, the strict CSS/JS separation rule, and the four-layer process for adding or renaming theme tokens
Use when writing or modifying Jest unit tests (*.unit.js) for Handsontable core, plugins, or utilities, or when a bug fix or internal refactor needs unit test coverage - covers Jest setup, test location conventions, mocking patterns, module aliases, and when to choose unit tests over E2E tests
Use when creating or modifying any .mjs file in the Handsontable monorepo - scripts, utilities, or library modules. Covers .mjs conventions, native node: imports, top-level await, cross-platform compatibility, and fs/promises async patterns. Trigger on any new .mjs file creation, not just files in scripts/ directories.
Use when a source code change needs a changelog entry, or before committing and pushing any bug fix, feature, or behavior change to source code - detecting when entries are required, categorizing changes correctly (added/changed/fixed/deprecated/removed/security), writing user-facing titles, and creating the JSON entry in .changelogs/