Repository: outsystems-datagrid Runtime Environment: User Browser (TypeScript/JavaScript) + OutSystems Server (.NET Extension) Last Updated: 2026-04-15
OutSystems Data Grid wraps the Wijmo FlexGrid library to deliver enterprise-grade spreadsheet functionality within OutSystems Reactive Web applications. The repository contains a TypeScript library that runs in the browser and a .NET extension that executes server-side to prepare OutSystems entity data for grid consumption.
graph TB
%% This repository components
Browser["OutSystems Data Grid<br/>Runs on: User Browser"]
Extension["DataGridUtils Extension<br/>Runs on: OutSystems Server"]
%% External services
WijmoLib[Wijmo FlexGrid v5.20252.44<br/>EXTERNAL]
OSApp[OutSystems Reactive App<br/>EXTERNAL]
%% Communication flows
OSApp -->|JavaScript API calls<br/>Synchronous| Browser
Browser -->|Wijmo FlexGrid API<br/>Synchronous| WijmoLib
OSApp -->|Server Action calls<br/>Synchronous| Extension
Extension -->|Returns JSON with metadata<br/>Synchronous| OSApp
Browser -->|DOM rendering<br/>Synchronous| OSApp
%% Styling
classDef thisRepo fill:#e0f2f1,stroke:#00796b,stroke-width:3px
classDef external fill:#ffe1e1,stroke:#d32f2f,stroke-width:2px,stroke-dasharray: 5 5
class Browser,Extension thisRepo
class WijmoLib,OSApp external
| External Service | Communication Type | Purpose |
|---|---|---|
| Wijmo FlexGrid v5.20252.44 | Sync (JavaScript API) | Third-party grid provider offering data virtualization, editing, filtering, sorting, grouping, export, and multi-panel architecture |
| OutSystems Reactive App | Sync (JavaScript API) | Consumer application instantiating and controlling grid instances via the OutSystems.GridAPI public API |
| OutSystems Platform | Sync (Server Actions) | Host platform executing the .NET extension server-side and loading the compiled JS module client-side |
| outsystems-datagrid-tests | Sync (WebDriver HTTP) | External test repository validating grid behavior across browsers via WebdriverIO + Cucumber |
The framework defines all grid behavior through abstract interfaces and classes in the OSFramework namespace, completely isolating OutSystems-specific logic from provider implementation details. Wijmo-specific code resides exclusively in the Providers namespace and implements these contracts. This abstraction enables swapping grid providers without modifying the OutSystems API surface or core grid logic.
Evidence:
src/OSFramework/DataGrid/Grid/IGrid.ts- defines grid contract without provider knowledgesrc/OSFramework/DataGrid/Column/AbstractColumn.ts- base column behavior independent of providersrc/Providers/DataGrid/Wijmo/Grid/FlexGrid.ts(inFlexGridclass) - implementsAbstractGridwith Wijmo providersrc/Providers/DataGrid/Wijmo/Grid/Factory.ts(inGridFactory.MakeGrid) - provider factory creates concrete implementationssrc/OSFramework/- zero references toProvidersnamespace across all 146 files, confirming one-way dependency
TypeScript namespaces (OSFramework, Providers, OutSystems) compile to a single AMD module without ES6 import statements. Layer boundaries are enforced by architectural convention: OSFramework must not reference Providers directly, Providers implements OSFramework interfaces, and OutSystems.GridAPI orchestrates both layers through factories.
Rationale: Namespace-based architecture with single-file compilation prevents circular dependencies and enforces unidirectional data flow. The API layer orchestrates, the framework defines contracts, and providers implement specifics.
Evidence:
tsconfig.json- compiles all TypeScript to single AMD moduledist/GridFramework.jsviaoutFileoptionsrc/OSFramework/- all 146 files declarenamespace OSFramework, no references toProvidersnamespacesrc/Providers/- all 59 files declarenamespace Providersand referenceOSFramework.DataGridinterfacessrc/OutSystems/GridAPI/GridManager.ts(inCreateGrid) - API layer delegates toProviders.DataGrid.Wijmo.Grid.GridFactory.MakeGrid
Grid capabilities (export, pagination, filtering, sorting, sanitization, etc.) are implemented as composable feature objects that each grid instance aggregates, rather than extending grid classes with feature methods. The ExposedFeatures class aggregates 31 feature properties, and the FeatureBuilder constructs all features via a fluent builder pattern.
Rationale: Composition provides flexibility to enable/disable features dynamically and test features in isolation. Each feature encapsulates its own state and Wijmo event handlers without polluting the grid class.
Evidence:
src/OSFramework/DataGrid/Feature/ExposedFeatures.ts(inExposedFeaturesclass) - aggregates 31 feature properties into single composable objectsrc/OSFramework/DataGrid/Feature/- contains 31 feature interface definitions (ICalculatedField,ICellData,IExport, etc.)src/Providers/DataGrid/Wijmo/Features/FeatureBuilder.ts(inFeatureBuilderclass) - fluent builder constructs all feature instances via_make*methodssrc/OSFramework/DataGrid/Grid/AbstractGrid.ts(inAbstractGridclass) - grid holds_featuresproperty of typeFeature.ExposedFeatures
Complex data preparation (OutSystems entity records to JSON with metadata extraction) occurs server-side via .NET extension before reaching the browser, keeping client-side code focused on presentation logic.
Rationale: Server-side transformation leverages OutSystems runtime metadata and type information unavailable in the browser. This separation reduces client computational load and ensures type-safe data handling with proper date formatting and field-type metadata.
Evidence:
extension/DataGridUtils/Source/NET/DataGridUtils.cs(inMssConvertData2JSON) - converts OutSystems objects to JSON with embedded metadataextension/DataGridUtils/Source/NET/ObtainMetadata.cs(ingetDataMetadata) - extracts column types and structure from .NET reflectionextension/DataGridUtils/Source/NET/temp_ardoJSON.cs- forked JSON serializer handling OutSystems-specific date conventionssrc/OutSystems/GridAPI/GridManager.ts(insetDataInGrid) - receives pre-formatted JSON string from server
Input sanitization occurs at two distinct boundaries: when data enters the grid from OutSystems (HTML escaping), and when data exits to clipboard/CSV export (formula injection prevention). The export sanitizer can be dynamically enabled or disabled at runtime via the public API.
Rationale: Defense-in-depth through multiple sanitization layers protects against distinct attack vectors (XSS via rendering, CSV injection via export) without coupling concerns. Each sanitization layer addresses specific threat models at appropriate system boundaries.
Evidence:
src/OSFramework/DataGrid/Helper/Sanitize.ts(inSanitizefunction) - replaces angle brackets with look-alike characters to prevent XSS when rendering user datasrc/OutSystems/GridAPI/GridManager.ts(insetDataInGrid) - conditionally sanitizes incoming data whengrid.config.sanitizeInputValuesis enabledsrc/Providers/DataGrid/Wijmo/Features/CellDataSanitizer.ts(inescapeCsvInjection) - neutralizes formula characters during clipboard/export operationssrc/OutSystems/GridAPI/Security.ts(inEnableCellDataSanitizer/DisableCellDataSanitizer) - runtime toggle for CSV injection protection
OutSystems API Layer (src/OutSystems/GridAPI/)
Exposes public JavaScript API consumed by OutSystems Reactive applications. Handles grid lifecycle, event subscriptions, and coordinates operations across framework and provider layers. Includes performance instrumentation (Performance/ subdirectory) wrapping all public API calls with timing marks.
Framework Layer (src/OSFramework/DataGrid/)
Provider-agnostic abstractions defining grid contracts, column types, events, features, and data source interfaces. Contains business logic independent of any specific grid library.
Provider Layer (src/Providers/DataGrid/Wijmo/)
Wijmo-specific implementations of framework interfaces. Directly interacts with wijmo.grid.FlexGrid library and translates between framework abstractions and Wijmo APIs. Leverages Wijmo's multi-panel architecture and row/column virtualization for performance with large datasets.
DataGridUtils Extension (extension/DataGridUtils/Source/NET/)
OutSystems Integration Studio extension that converts OutSystems entity records and structures to JSON format with embedded metadata. Runs in OutSystems application server process. See docs/adr/ADR-0001-Extension-Dotnet-Upgrade-And-Improvements.md for .NET upgrade decisions.
The TypeScript codebase compiles to a single AMD module (dist/GridFramework.js) that OutSystems applications load as a script resource. The .NET extension compiles to a DLL and deploys with OutSystems platform.
Run npm run build for production artifacts or npm run dev for browser-sync on port 3000. See gulpfile.js and gulp/Tasks/ for build orchestration details.