Refactor Vue 3 integration guide to use composables pattern#1657
Refactor Vue 3 integration guide to use composables pattern#1657
Conversation
Add idiomatic code examples to React, Angular, Vue, and Svelte integration pages showing HyperFormula initialization and reading calculated values. Each guide uses framework-specific patterns (React hooks, Angular service, Vue ref/markRaw, Svelte reactivity). Closes HF-122.
Per feedback, snippets now focus on framework-specific integration patterns (useRef/useEffect, @Injectable, markRaw/ref, Svelte reactivity) with placeholder comments for data and configuration rather than concrete values. The Demo section link is reworded from "Explore the full working example" to "For a more advanced example" to signal that the Stackblitz demo is a richer, separate project. Part of HF-122.
Expand React, Angular, Vue and Svelte integration guides to cover framework-specific concerns that the previous skeleton snippets omitted: - Convert all snippets to TypeScript with HyperFormula/CellValue imports - Add licenseKey: 'gpl-v3' to every buildFromArray call - Inline `npm install hyperformula` install command - React: runnable JSX with controlled inputs, try/catch around setCellContents, React.StrictMode note, Next.js App Router SSR section with 'use client' and dynamic import - Angular: modern standalone component + inject() + DestroyRef + Signals + OnPush, RxJS BehaviorSubject variant with AsyncPipe import note, NgZone runOutsideAngular section, provider-scope + DestroyRef rationale - Vue: <script setup lang="ts">, expanded markRaw Proxy explanation and shallowRef trap, Nuxt SSR snippet, Pinia store with updateCell action, valuesUpdated event hook, inline v-for template - Svelte: fixes memory leak by adding onDestroy(() => hf.destroy()), Svelte 5 runes primary example plus Svelte 4 delta, SvelteKit SSR warning banner and dedicated onMount section with dynamic import, wired #each template with updateCell handler
Point readers from each integration guide to related topics they are likely to need next: configuration options, basic operations (CRUD), advanced usage (multi-sheet, named expressions), and custom functions. Identical section in all four guides so the navigation experience is consistent when switching between frameworks.
The Stackblitz demo links used \${...} JavaScript template literal syntax,
which is not interpolated by VuePress. VuePress 1 processes markdown as
Vue templates, so the correct syntax for accessing the injected
\$page.buildDateURIEncoded variable is Vue's {{ ... }} interpolation.
config.js line 79 documents the intended syntax explicitly:
// inject current HF buildDate URI encoded as {{ \$page.buildDateURIEncoded }} variable
Before this fix, the cache-buster query string rendered as a literal
?v=\${\$page.buildDateURIEncoded} in the URL, breaking the cache-busting
behaviour on every Stackblitz demo link.
Note: the same issue exists in docs/guide/custom-functions.md:361 from
an earlier change; that is left for a separate fix.
…ntent) tsc smoke check found that updateCell(value: unknown) does not satisfy setCellContents which expects RawCellContent. Replace unknown with the correct type and add missing RawCellContent imports in Angular, Vue and Svelte guides.
Add framework-agnostic instruction file for AI coding assistants (Claude Code, GitHub Copilot, Cursor, Gemini CLI). Covers the core 3-operation API surface, framework integration patterns with critical rules (markRaw, onDestroy, StrictMode, DestroyRef, SSR guards), key types, common mistakes to prevent, and project structure pointers.
Angular: switch primary pattern to BehaviorSubject/Observable (module-based), matching the angular-demo on Stackblitz. Signal-based variant moved to a 'Signals variant (Angular 17+)' note. Cleanup section expanded with both ngOnDestroy and DestroyRef options. Svelte: switch primary pattern to Svelte 4 style (on:click, plain let), matching the svelte-demo on Stackblitz. Svelte 5 runes variant moved to a '### Svelte 5 (runes)' subsection. SSR section updated to use Svelte 4 as primary. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
React: fix Next.js SSR pattern — 'use client' belongs in the component
file, not on page.tsx; server page uses dynamic(..., { ssr: false })
Angular: add CommonModule/standalone imports for *ngFor + async pipe;
add @for template for signals variant; add inject() context note
Vue: replace shallowRef with ref in Nuxt SSR snippet (shallowRef vs
markRaw contradiction); add hf.off() teardown to valuesUpdated example;
remove hf from Pinia store return value (devtools serialisation risk)
Svelte: fix CellValue type for result variable; fix SSR snippet to use
onMount return for cleanup instead of separate onDestroy
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Vue: rewrite primary snippet to use class wrapper pattern matching
the vue-3-demo on Stackblitz. markRaw moved to Notes as alternative.
Angular: remove unnecessary `as CellValue[][]` casts (getSheetValues
already returns this type).
React: remove try/catch from handleCellEdit for consistency — no demo
uses error handling around setCellContents.
custom-functions.md: fix VuePress template syntax (${}→{{}}) so the
Stackblitz link renders the build date correctly.
AGENTS.md: update framework table to match actual guide primary
patterns (Angular=BehaviorSubject, Vue=class wrapper, Svelte=Svelte 4).
…polation
{{ $page.buildDateURIEncoded }} inside markdown link syntax [text](url{{ }})
breaks markdown-it parsing — links render as plain text instead of clickable
links. Switch to <a :href="..."> with Vue v-bind which VuePress handles
correctly since page data is available in template scope.
Per Kuba's review feedback: snippets must match what's in the Stackblitz demos so we can guarantee they work correctly. Removed all patterns that have never been tested with HyperFormula: Angular: removed Signals variant (signal, inject, DestroyRef, OnPush, @for), NgZone.runOutsideAngular section. Svelte: removed Svelte 5 runes ($state) section. Vue: removed markRaw alternative, Nuxt SSR with dynamic import, valuesUpdated event listener, Pinia store sections. These patterns can be re-added once validated by a framework consultant or included in updated demos.
All four Stackblitz demos use the same interaction model: "Run calculations" and "Reset" buttons with read-only table output. Aligned guides to match: React: replaced editable <input onChange> with button-driven calculate/reset. The onChange-per-keystroke pattern was not from the demo and caused issues with partial formula input. Angular: replaced standalone component with NgModule pattern (matching demo). Replaced updateCell with calculate/reset methods matching EmployeesService. Added buttons to template. Vue: replaced dead handleUpdate/updateCell with getCalculatedValues/ getRawFormulas matching EmployeesDataProvider. Added Run/Reset buttons.
AGENTS.md: Vue SSR guard updated from "onMounted + dynamic import" to "<ClientOnly> (Nuxt)" matching the actual guide content. Svelte: renamed "Calculate" to "Run calculations" and added "Reset" button for consistency with React/Angular/Vue guides. Reset is pure UI (result = null), no HF API involved.
Switch the basic example from a class wrapper to a composable, the idiomatic Vue 3 pattern for stateful reuse. Correct the reactivity explanation: TypeScript's `private` is erased at compile time, so the class did not actually shield the instance from Vue's Proxy — what keeps the engine out of reactivity is simply not passing it to ref()/reactive(). Use shallowRef for the values grid so reassignment triggers re-renders without deep-proxying every row. Use HyperFormula's own Sheet and CellValue types instead of hand-rolled unions. Expand the markRaw section to clarify when it is and isn't needed.
Performance comparison of head (443c87b) vs base (d6a316c) |
|
Picked nothing up from this PR into #1653 — the composables refactor ( The bug surfacing in this review ( Closing-suggestion: park until the Vue specialist task lands. I'll let you close at your discretion. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #1657 +/- ##
===========================================
+ Coverage 96.77% 97.18% +0.41%
===========================================
Files 174 174
Lines 15086 15086
Branches 3223 3223
===========================================
+ Hits 14599 14662 +63
+ Misses 487 424 -63 🚀 New features to boost your workflow:
|
Context
The Vue 3 integration guide was using an outdated pattern with a plain class wrapper (
SpreadsheetProvider) to keep the HyperFormula instance outside Vue's reactivity system. This approach is less idiomatic for modern Vue 3 development.The guide has been updated to demonstrate the recommended composable pattern, which is the standard way to encapsulate stateful logic in Vue 3. This change also improves the clarity of the troubleshooting section by better explaining when and why
markRawis needed.How did you test your changes?
Documentation review only. The changes are instructional updates to the integration guide with no functional code changes to the library itself.
Types of changes
Related issues:
None
Checklist:
Summary of changes
SpreadsheetProviderpattern with a composable functionuseSpreadsheet<script setup>shallowRefusagemarkRawis needed vs. when it's unnecessary<ClientOnly>wrapper with proper contexttype="button"attributes to button elements for better HTML semanticshttps://claude.ai/code/session_01FBwp6T1sLtGPiWUKHMn8hH