@syncfusion/ej2-spreadsheet
Version:
Feature-rich JavaScript Spreadsheet (Excel) control with built-in support for selection, editing, formatting, importing and exporting to Excel
66 lines (54 loc) • 6.7 kB
Markdown
# Cell Renderer Module data flow
## What It Does
Documents how cell data models and their DOM rendering are coordinated. The Workbook layer defines the `Cell` model and helpers to get/set cell data and formatting; the Spreadsheet renderer produces DOM cell nodes, applies formatted text, templates, images/charts, wrapping, merges and triggers formula calculation notifications.
Primary files: `src/workbook/base/cell.ts` (Core cell model & helpers) and `src/spreadsheet/renderer/cell.ts` (UI CellRenderer).
## Entry Points (Core)
**Module / Class:** `Cell` (Workbook base)
- Models: `Cell` defines model properties: `value`, `formula`, `format`, `style`, `wrap`, `colSpan`/`rowSpan`, `image`, `chart`, `comment`/`notes`, `isLocked`, `validation`, etc.
- Helpers:
- `getCell(rowIndex, colIndex, sheet, isInitRow?, returnEmptyObjIfNull?)` — retrieve a `CellModel`, optionally initializing row/cells.
- `setCell(rowIndex, colIndex, sheet, cell, isExtend?)` — persist a `CellModel`; `isExtend` merges properties instead of replacing.
- `skipDefaultValue(style)` — return only changed style props (used during serialization/export).
- `wrap(address, wrap, context, preventEvt?, isPublic?)` — apply wrapping to a range by updating cells and notifying `wrapEvent`.
- `getColorCode(format)` and `isCustomDateTime(format, ...)` — format utilities used by number/date formatters and renderers.
- Lifecycle: `OpenSettings` config is defined here; not directly rendering but essential for model consistency during open/save flows.
## Entry Points (UI)
**Class:** `CellRenderer` (Spreadsheet renderer)
- Responsibilities:
- `renderColHeader(index, row, refChild?)` / `renderRowHeader(index, row, refChild?)` — build header `<th>` and row-number cells.
- `render(args: CellRenderArgs)` — render a cell element (`td`) for given `rowIdx`/`colIdx` and `CellModel`: handle merges, templates, conditional format hooks, filter icons and insert into row.
- `update(args: CellRenderArgs)` — core per-cell update path: template processing, formula calculation invocation, formatting (`getFormattedCellObject`), hyperlink handling, merge/span handling, note/comment indicators, image/chart creation and style application.
- `refreshRange(range, ...)` / `refresh(rowIdx, colIdx, ...)` — public refresh APIs used after data/model changes to re-render ranges or single cells.
- Helpers: `createImageAndChart(args)`, `calculateFormula(args)`, `checkMerged(args)`, `mergeFreezeRow()`/`mergeFreezeCol()`, `setWrapByValue()` and template compilation utilities.
- Events wired: `updateView`, `calculateFormula` subscriptions; triggers `beforeCellRender` and notifies other subsystems via `parent.notify(...)`.
## ASCII Flow (high-level)
Model change (API / user edit / import) → Core updates via `setCell()` or model calls → Spreadsheet notifies renderer (`updateView` / `refreshRange`) → `CellRenderer.render/update()` invoked per cell → if formula present then `calculateFormula()` triggers `workbookFormulaOperation` notifications → formatting request `getFormattedCellObject` returns formatted text → renderer `refreshNode()` inserts formatted content and applies styles, images/charts, merge attributes, and accessibility attributes.
## Operations & Responsibilities
- Model operations (Core):
- `getCell`/`setCell`: authoritative read/write for cell data; ensure row arrays exist, support in-place extension to preserve properties.
- `wrap()`: iteratively call `updateCell`/notify wrap events for ranges.
- Format utilities: `getColorCode()` and `isCustomDateTime()` help renderer and formatters decide presentation.
- Rendering operations (UI):
- Template processing: `processTemplates()` / `compileCellTemplate()` resolve range templates and compile templates safely (handles string templates, selectors and framework portals).
- Formatting handshake: renderer constructs `NumberFormatArgs` and notifies `getFormattedCellObject` to receive `formattedText`, `color`, and alignment hints.
- Formula handling: `calculateFormula()` fires `workbookFormulaOperation` with `refreshCalculate` action; renderer updates cell `.value` based on core calculation results.
- Merge & freeze interplay: merge detection (`checkMerged`) coordinates merged cell placeholders with frozen rows/cols logic (`mergeFreezeRow`, `mergeFreezeCol`) updating DOM and z-indexes.
- Visual extras: note/comment indicators, hyperlink wrapping, image/chart insertion via `setChart` and image handlers; conditional formatting applied via `applyCF` notifications.
## Validation & Safety
- Null-safe model access: `getCell(..., returnEmptyObjIfNull)` lets renderer inspect model without creating missing structures unintentionally.
- Template security: compiled templates use the existing `compile()` pipeline and guard against invalid selectors via `isSelector()`.
- Formula ordering: renderer ensures formulas are recalculated (or queued) via `workbookFormulaOperation` notifications; `parent.calculationMode` is respected to avoid unexpected work on manual mode.
- View safety: `refreshRange()` first verifies `inView()` and virtualization constraints to avoid rendering off-screen cells unnecessarily.
- Cleanup: `destroy()` detaches event listeners and DOM nodes to avoid leaks.
## Desired Outputs
- User-facing: accurate cell DOM reflecting cell model (value, formatted text, templates, images/charts, wrapped text, merges and hyperlinks) with correct ARIA attributes and keyboard focus behavior.
- System-level: coordinated notifications between renderer and core for formatting and formulas; minimal redundant DOM updates by batching refreshes via `refreshRange()`.
## Implementation Notes
- Keep `getCell`/`setCell` as the single source of truth for model read/write; avoid direct mutation of `sheet.rows` outside these helpers.
- Prefer `isInitRow` when the renderer needs to ensure row structures exist rather than always creating them during reads.
- When rendering many cells, accumulate cloned nodes for height measurement (as `getRowHeightOnInit()` does) and apply size updates once per-row to reduce layout thrash.
- Always call `parent.notify(getFormattedCellObject, args)` instead of embedding formatting logic in the renderer.
- Destroy child UI resources (compiled templates, created DropDowns/Buttons from cell templates) in `destroy()` to prevent memory leaks.
## Key Events & Hooks
- Renderer subscribes to: `updateView`, `calculateFormula`, `renderFilterCell`, and triggers/uses: `beforeCellRender`, `getFormattedCellObject`, `applyCellFormat`, `createNoteIndicator`, `setChart`, `deleteNote`, `deleteComment`, `wrapEvent`, and `workbookFormulaOperation`.
---