Skip to content
cccskills
FreePublished on GitHub

creating-docs-examples

Create Handsontable documentation examples for JavaScript, TypeScript, React, Angular, and Vue. The skill explains source files, generated JavaScript, required imports and license settings, embedding examples in guides, and checking that each framework version displays correctly.

OriginalShow the original description

Use when creating code examples for documentation pages - JavaScript, TypeScript, React, Angular, and Vue variants with proper imports, registration, and license key

See how to install

Good for

  • Adding a code example to a feature guide
  • Preparing examples for multiple frameworks
  • Generating JavaScript examples from TypeScript
  • Updating Vue examples and checking Angular examples

Files included (1)

  • SKILL.md10.0 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

Creating Documentation Code Examples

File structure

docs/content/guides/category/feature/
  feature.md                 # The guide page
  javascript/example1.ts     # Primary source; example1.js is generated
  react/example1.tsx         # Primary source; example1.jsx is generated
  angular/example1.ts        # plus example1.html (outer wrapper)
  vue/example1.vue           # TypeScript SFC (`<script setup lang="ts">`)

Rules

  • 25-60 lines per example, one concept each. Number by complexity: example1 basic setup, example2 a configuration variation, example3 advanced.
  • Write the .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/); generated JS files are overwritten, so change the TS source. Vue has no JS variant.
  • Use createSpreadsheetData() or domain-appropriate data (product names, dates, currencies).

Required in every example

  1. Base import and explicit registration (tree-shaking examples import individual plugins and cell types instead of registerAllModules()):
    import Handsontable from 'handsontable/base';
    import { registerAllModules } from 'handsontable/registry';
    registerAllModules();
    
  2. licenseKey: 'non-commercial-and-evaluation'
  3. Container, typed in the .ts and .tsx files: const container = document.querySelector<HTMLElement>('#example1')!;. An untyped querySelector returns Element | null, which fails with TS2345 in a new file, and it also hides every later error in the settings object from the type check (see docs/AGENTS.md, "Type-checking the examples"). The generated .js file keeps the plain document.querySelector('#example1').

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 components (standalone: true, imports: [HotTableModule]), class named AppComponent in every example.
  • app.config.ts (not app.module.ts) with ApplicationConfig, provideZoneChangeDetection({ eventCoalescing: true }), and global HOT_GLOBAL_CONFIG for the license key. Set the license there only; leave licenseKey off individual <hot-table> bindings.
  • Template control flow: @if / @for (x of list; track x.id).

The docs site bootstraps Angular examples with JIT in the browser, which cannot load external files and lacks decorator metadata:

  • Inline styles: styles: ['...']. The example-runner injects CSS globally via the --css slot, and styleUrls fails.
  • Inline template: template: \...`. angular/example1.htmlis the outer wrapper (selector tag) the example-runner consumes, not the component template;templateUrl` fails.
  • Inject services with inject(). Constructor DI throws NG0202.
  • Put Handsontable hook functions inside gridSettings, not as template bindings ((afterInit)="handler()").
  • Import only the symbols you use; unused imports (RowObject, ViewChild, NgFor) can cause module resolution errors.
  • Set template-bound state (such as hotSettings read by @if) in ngOnInit. Angular 22 components are OnPush by default, and nothing marks the component dirty after ngAfterViewInit, so a write there leaves an @if grid blank. If the write needs the view, call markForCheck() on an injected ChangeDetectorRef after it, or detectChanges() when the view must render synchronously.
  • Mark the component dirty after any write to template-bound state that happens after an await, in a setTimeout, or in a Handsontable callback such as a hook or a shortcut action (status text, a disabled button). Angular 22 components are OnPush by default, and NgZone.run does not mark them dirty. Call markForCheck() on an injected ChangeDetectorRef: outside the zone it schedules its own tick, so a Handsontable callback needs nothing more. Keep detectChanges() for a view that must render synchronously. Verify by loading the page and waiting, with no interaction.

The .ts file holds app.component.ts and app.config.ts as separate /* file: ... */ sections:

/* 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 */

angular/example1.html:

<div>
  <example1-feature-name></example1-feature-name>
</div>

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 drops script nodes from the body fragment; mergeCompanionHtmlForStackBlitz wires it into the StackBlitz template). Examples with no HTML tab keep the default mount markup.

See skill angular-wrapper-dev for the full reference.

Vue 3

Write every new or updated example as a TypeScript SFC: one exampleN.vue per example, Composition API, <script setup lang="ts">. The example-runner (docs/src/scripts/example-runner.ts) loads vue/example*.vue and mounts them with createApp(). When you touch an old split exampleN.js + exampleN.html example, migrate it to a .vue SFC. New examples use the Composition API, not defineComponent with data()/methods.

<script setup lang="ts">
import { ref } from 'vue';
import { HotTable } from '@handsontable/vue3';
import { registerAllModules } from 'handsontable/registry';
import type { GridSettings } from 'handsontable/settings';

registerAllModules();

const hotSettings = ref<GridSettings>({
  data: [
    ['Acme Corp', 'Q1 2025', '$4.2M'],
    ['Vertex Industries', 'Q1 2025', '$18.7M'],
  ],
  colHeaders: true,
  height: 'auto',
  licenseKey: 'non-commercial-and-evaluation',
});
</script>

<template>
  <div id="example1">
    <HotTable :settings="hotSettings" />
  </div>
</template>
  • Type grid options with GridSettings from handsontable/settings; add local type aliases for object rows.
  • Call registerAllModules() once at the top level of <script setup>, outside onMounted.
  • Import HotTable and HotColumn from @handsontable/vue3; using them in <template> registers them (no global app.component() registration).
  • licenseKey goes inside the settings object.
  • The root <div> id matches the guide's example container (#example1 in ::: example #example1 :vue3).
  • Prefer a single :settings object; use individual props only when the guide text highlights one.
  • Put hooks (afterChange, beforeDataProviderFetch, etc.) inside the settings object, not as Vue event listeners on <HotTable>.
  • ref() holds reactive state the template or handlers update. Use a plain const for hotSettings when deep reactivity would trigger unwanted updateSettings() calls (e.g. only a status label changes beside the grid).
  • Template refs bound via ref="..." use useTemplateRef('refName'), never ref(), with the string matching the template ref attribute exactly:
const hotRef = useTemplateRef<InstanceType<typeof HotTable>>('hotRef');   // <HotTable ref="hotRef" :settings="hotSettings" />
const dropdownRef = useTemplateRef<HTMLDivElement>('dropdownRef');         // <div ref="dropdownRef" class="theme-dropdown">

Access the grid with hotRef.value?.hotInstance, a DOM element with dropdownRef.value.

  • HotColumn nests inside <HotTable> in <template>, with column options via :settings on each.
  • <style scoped> is allowed for example-only UI; the guide's --css slot CSS still applies globally.

Presets on the ::: example directive select dependencies: :vue3 (default), :vue3-languages, :vue3-vuex. Match the preset to the feature.

Embedding a Vue SFC (single tab, no --html / --js):

::: example #example1 :vue3

@[code](@/content/guides/category/feature/vue/example1.vue)

:::

See skill vue-wrapper-dev for wrapper behavior.

Embedding in the guide

Embed the files with @[code] inside an ::: example container; syntax in the writing-docs-pages skill.

Checklist

  • TypeScript source written (.ts/.tsx, or .vue with lang="ts"); JS variant generated, not hand-written.
  • licenseKey: 'non-commercial-and-evaluation', handsontable/base import plus registration.
  • 25-60 lines, one concept, realistic data.
  • Every framework variant rendered and looked at: open the page in the docs dev server (npm --prefix docs run dev, not a full docs build) and check each variant for console load errors, grid width, and styling. A variant you did not open counts as untested.
  • Angular variants type-check: SKIP_LATEST=1 npm run typecheck --prefix docs/angular-type-check (as CI runs it; without SKIP_LATEST it also checks against handsontable@latest, so an API added on the branch fails locally) (needs handsontable and wrappers/angular-wrapper built first). This is the Docs Angular Type Check CI job, which fails most often after an example edit.

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Develop and modify the Handsontable Angular wrapper with guidance on component lifecycle, settings updates, and NgZone, which controls change detection. It also covers standalone examples, global configuration, and the build and test workflow.

  • Fix settings updates in the Angular wrapper
  • Review change detection around grid operations
  • Update examples to standalone components
handsontable/handsontable22.1KUpdated Oct 19, 2026

Open local or public web pages in BrowserStack Live for checks on real mobile devices or desktop browsers. The skill prepares temporary access to a local server, launches the requested session, and shares its dashboard link.

  • Check a local page on an Android device
  • Open a page in Safari on an iPhone or iPad
  • Inspect behavior in a specific desktop browser
handsontable/handsontable22.1KUpdated Oct 19, 2026

Prepare user-facing changelog entries for source code changes. The skill determines whether an entry is needed, classifies the change, writes a clear title, and uses the project CLI to create a JSON file tied to the pull request.

  • Add a changelog entry for a bug fix
  • Classify a new feature or behavior change
  • Explain a breaking change and its replacement
handsontable/handsontable22.1KUpdated Oct 19, 2026

code-graph

FreeSummary

Explore relationships between functions and files using a prebuilt code graph, a map of code dependencies. Trace bugs, inspect callers and execution paths, and assess the impact of refactoring or proposed changes.

  • Explore callers and dependencies in unfamiliar code
  • Trace a bug across multiple files
  • Assess the impact of renaming or removing code
handsontable/handsontable22.1KUpdated Oct 19, 2026

Work with Handsontable row and column positions by distinguishing source data, displayed order, and rendered cells. It guides index conversion and helps investigate misplaced data when sorting, filtering, hiding, or moving rows and columns.

  • Investigating misplaced rows or columns
  • Converting between source and displayed indexes
  • Combining filters with manual column movement
handsontable/handsontable22.1KUpdated Oct 19, 2026

Build Handsontable demo pages for visual regression tests, which compare screenshots for appearance changes. It guides feature routes, URL-driven display states, sample data, and decisions about testing the same feature across framework wrappers.

  • Adding a demo route for a new feature
  • Creating multiple visual states through URL parameters
  • Planning visual coverage across framework wrappers
handsontable/handsontable22.1KUpdated Oct 19, 2026

See all skills by handsontable

Report a problem with this skill