# RevoGrid Documentation Full Export Generated from source Markdown for https://rv-grid.com. Generated type API pages, blog posts, comparison pages, legal policies, and hidden partials are intentionally excluded. --- # JavaScript Data Grid for Complex Web Apps Source: https://rv-grid.com/ Description: Build spreadsheet-grade data grids with Vue, React, Angular, Svelte, Dash, Python, and JavaScript apps. This page is rendered from VitePress frontmatter and Vue components; no standalone Markdown body is available in the normalized export. --- # React Data Grid — Fast, Editable, Virtual Scroll | RevoGrid Source: https://rv-grid.com/react-data-grid Description: A high-performance React data grid with virtual scrolling, inline editing, and custom React cell renderers. Open-source core, per-developer licensing, built for data-heavy React apps. This page is rendered from VitePress frontmatter and Vue components; no standalone Markdown body is available in the normalized export. --- # Vue Data Grid - Fast, Editable, Virtual Scroll | RevoGrid Source: https://rv-grid.com/vue-data-grid Description: A high-performance Vue data grid with virtual scrolling, inline editing, and custom Vue cell renderers. Open-source core, per-developer licensing, built for data-heavy Vue 3 apps. This page is rendered from VitePress frontmatter and Vue components; no standalone Markdown body is available in the normalized export. --- # Angular Data Grid - Fast, Editable, Virtual Scroll | RevoGrid Source: https://rv-grid.com/angular-data-grid Description: A high-performance Angular data grid with virtual scrolling, inline editing, and custom Angular cell renderers. Open-source core, per-developer licensing, built for data-heavy Angular apps. This page is rendered from VitePress frontmatter and Vue components; no standalone Markdown body is available in the normalized export. --- # Svelte Data Grid - Fast, Editable, Virtual Scroll | RevoGrid Source: https://rv-grid.com/svelte-data-grid Description: A high-performance Svelte data grid with virtual scrolling, inline editing, and custom Svelte cell renderers. Open-source core, per-developer licensing, built for data-heavy Svelte apps. This page is rendered from VitePress frontmatter and Vue components; no standalone Markdown body is available in the normalized export. --- # RevoGrid Pro Source: https://rv-grid.com/pro Description: JavaScript Kanban, Pivot, Gantt, Scheduling, Spreadsheet formulas, master-detail grids, and audit history without building the data layer from scratch. This page is rendered from VitePress frontmatter and Vue components; no standalone Markdown body is available in the normalized export. --- # RevoGrid Pro Pricing and Feature Comparison Source: https://rv-grid.com/pro/feature-table Description: Compare RevoGrid Community, Pro Lite, and Pro Advanced plans, including advanced grid features, support options, and upgrade paths.
# RevoGrid Pro pricing and feature comparison [Watch the feature overview](https://rv-grid.com/pro)

Choose this page when you need a quick answer to: - which advanced features are included in each plan - whether a feature is part of Community or Pro - which plan includes advanced support For a higher-level overview, go back to [RevoGrid Pro](https://rv-grid.com/pro/).
### Useful links [Privacy Policy](https://rv-grid.com/pro/policies/privacy) | [Terms of Service](https://rv-grid.com/pro/policies/terms) | [License](https://rv-grid.com/pro/policies/license) | [Security Policy](https://rv-grid.com/pro/policies/security) | Contact us
### Frequently asked questions
::: details How many developer licenses do I need? The number of licenses required must match the maximum number of concurrent developers contributing to the front-end code. **Examples:** - **Example 1**: A project has 3 front-end developers and 10 back-end developers. If only the 3 front-end developers work with RevoGrid Pro, you need 3 licenses. - **Example 2**: A UI team with 2 front-end developers uses RevoGrid Pro as part of a shared library for multiple apps. If the apps have 5 and 3 front-end developers, you will need 10 licenses (2 + 5 + 3). For more details, refer to the relevant clause in the [EULA](https://rv-grid.com/pro/policies/license#_3-4-1-Required-quantity-of-licenses). ::: ::: details Am I allowed to use the product after the update entitlement expires? Yes, you can continue using the product in production environments after the update entitlement expires. **However**: - You need an active subscription to continue development. - Updates, new features, and technical support require a valid subscription. To renew, contact [sales](mailto:contact@revolist.eu). ::: ::: details Do developers have to be named? No. Licenses are transferable between developers when team members join or leave projects. We trust that your team will not exceed the number of licensed developers. ::: ::: details What is the policy on redistributing the software? RevoGrid Pro licenses are royalty-free for: - Internal company solutions. - Hosted applications. - Commercial solutions deployed to end users. If sublicensing is needed, it must be part of a larger work, and sublicenses must follow the same [EULA terms](https://rv-grid.com/pro/policies/license). Examples: - **Example 1:** Agency ‘A’ builds apps for two clients and sublicenses RevoGrid components. No extra fee is needed if the apps are used without source modification. - **Example 2:** If clients modify the application themselves, they must purchase their own licenses. For custom use cases or licensing concerns, please [contact sales](mailto:contact@revolist.eu). ::: ::: details Do you offer discounts to educational and non-profit organizations? Yes, we offer a 50% discount for students, instructors, non-profits, and charities. To qualify: - Provide proof of affiliation (e.g., an email from an official account). [Contact sales](mailto:contact@revolist.eu) to apply. ::: ::: details Why must we license developers not using the software directly? All developers contributing to a project using RevoGrid Pro must be licensed, even if they only use it indirectly (e.g., via a wrapper library). This ensures fair licensing and helps teams comply easily. The per-developer price is adjusted to account for this broader requirement. Learn more in the [EULA](https://rv-grid.com/pro/policies/license). ::: ::: details Need Help? {open dashed} If you have questions or need support, reach out: - For sales-related inquiries: [contact sales](mailto:contact@revolist.eu). - For product issues, [open a GitHub issue](https://github.com/revolist/revogrid/issues). ::: :::: details Is there a deployment fee? No. RevoGrid Pro does not currently charge a deployment fee. Your license costs are based on the selected plan and the required number of developer licenses, not on how many times you deploy. For custom licensing questions, please [contact sales](mailto:contact@revolist.eu). ::::
--- # RevoGrid Pro Feature Videos and Demos Source: https://rv-grid.com/pro/videos Description: Watch RevoGrid Pro feature videos and interactive demos for advanced data grid plugins, editing, layout, filtering, validation, and enterprise workflows.
# RevoGrid Pro Feature Videos Click on the features below to see video previews, explore the feature demos below, or [compare our plans](https://rv-grid.com/pro).




### Frequently asked questions
::: details How many developer licenses do I need? The number of licenses required must match the maximum number of concurrent developers contributing to the front-end code. **Examples:** - **Example 1**: A project has 3 front-end developers and 10 back-end developers. If only the 3 front-end developers work with RevoGrid Pro, you need 3 licenses. - **Example 2**: A UI team with 2 front-end developers uses RevoGrid Pro as part of a shared library for multiple apps. If the apps have 5 and 3 front-end developers, you will need 10 licenses (2 + 5 + 3). For more details, refer to the relevant clause in the [EULA](https://rv-grid.com/pro/policies/license#_3-4-1-Required-quantity-of-licenses). ::: ::: details Am I allowed to use the product after the update entitlement expires? Yes, you can continue using the product in production environments after the update entitlement expires. **However**: - You need an active subscription to continue development. - Updates, new features, and technical support require a valid subscription. To renew, contact [sales](mailto:contact@revolist.eu). ::: ::: details Do developers have to be named? No. Licenses are transferable between developers when team members join or leave projects. We trust that your team will not exceed the number of licensed developers. ::: ::: details What is the policy on redistributing the software? RevoGrid Pro licenses are royalty-free for: - Internal company solutions. - Hosted applications. - Commercial solutions deployed to end users. If sublicensing is needed, it must be part of a larger work, and sublicenses must follow the same [EULA terms](https://rv-grid.com/pro/policies/license). Examples: - **Example 1:** Agency ‘A’ builds apps for two clients and sublicenses RevoGrid components. No extra fee is needed if the apps are used without source modification. - **Example 2:** If clients modify the application themselves, they must purchase their own licenses. For custom use cases or licensing concerns, please [contact sales](mailto:contact@revolist.eu). ::: ::: details Do you offer discounts to educational and non-profit organizations? Yes, we offer a 50% discount for students, instructors, non-profits, and charities. To qualify: - Provide proof of affiliation (e.g., an email from an official account). [Contact sales](mailto:contact@revolist.eu) to apply. ::: ::: details Why must we license developers not using the software directly? All developers contributing to a project using RevoGrid Pro must be licensed, even if they only use it indirectly (e.g., via a wrapper library). This ensures fair licensing and helps teams comply easily. The per-developer price is adjusted to account for this broader requirement. Learn more in the [EULA](https://rv-grid.com/pro/policies/license). ::: ::: details Need Help? {open dashed} If you have questions or need support, reach out: - For sales-related inquiries: [contact sales](mailto:contact@revolist.eu). - For product issues, [open a GitHub issue](https://github.com/revolist/revogrid/issues). ::: :::: details Is there a deployment fee? No. RevoGrid Pro does not currently charge a deployment fee. Your license costs are based on the selected plan and the required number of developer licenses, not on how many times you deploy. For custom licensing questions, please [contact sales](mailto:contact@revolist.eu). ::::
--- # Fast JavaScript Pivot Table for Web Source: https://rv-grid.com/pivot Description: JavaScript Pivot Table with linked charts for React, Vue, Angular, or vanilla JavaScript applications. This page is rendered from VitePress frontmatter and Vue components; no standalone Markdown body is available in the normalized export. --- # JavaScript Kanban Board Component Source: https://rv-grid.com/kanban Description: RevoGrid Kanban is a virtualized JavaScript Kanban board component for drag-and-drop workflows, swimlanes, WIP limits, custom cards, and large task datasets. This page is rendered from VitePress frontmatter and Vue components; no standalone Markdown body is available in the normalized export. --- # JavaScript Gantt Chart Component Source: https://rv-grid.com/gantt Description: RevoGrid Gantt is a fast JavaScript Gantt chart for data-heavy web apps, with virtualization, dependencies, resources, critical path, and a live 10,000-task demo. This page is rendered from VitePress frontmatter and Vue components; no standalone Markdown body is available in the normalized export. --- # JavaScript Scheduler & Event Calendar | RevoGrid Scheduler Source: https://rv-grid.com/jsscheduler Description: RevoGrid Scheduler is a JavaScript Scheduler and event calendar for resource timelines, staff shifts, bookings, availability, and capacity planning. This page is rendered from VitePress frontmatter and Vue components; no standalone Markdown body is available in the normalized export. --- # JavaScript Data Grid Quick Start Source: https://rv-grid.com/guide Description: Learn how to install RevoGrid, render your first JavaScript data grid, and move from a basic setup to filtering, editing, and framework integrations. RevoGrid is a high-performance [MIT-licensed](https://rv-grid.com/guide/licensing) JavaScript data grid built for large datasets, fast scrolling, and spreadsheet-like interactions. It works as a Web Component, so the same core grid can be used in JavaScript, [TypeScript](https://rv-grid.com/guide/ts/), [React](https://rv-grid.com/guide/react/), [Angular](https://rv-grid.com/guide/angular/), [Vue](https://rv-grid.com/guide/vue3/), [Svelte](https://rv-grid.com/guide/svelte/), and other modern frontends. [Explore the full RevoGrid Data Grid →](https://rv-grid.com/) ## Quick start in 60 seconds This page is the fastest way to get a JavaScript data grid on the screen with RevoGrid. From here you can move into feature guides, framework-specific setup, and the full [API](https://rv-grid.com/guide/api/revoGrid). For prototypes, internal tools, or plain HTML pages, load RevoGrid directly from a CDN: ```html ``` ## Why teams use RevoGrid - [Virtual rows and columns](https://rv-grid.com/guide/performance) keep rendering fast as datasets grow. - Built-in [focus](https://rv-grid.com/guide/defs#Focus), [range selection](https://rv-grid.com/guide/defs#Range), [editing](https://rv-grid.com/guide/editing), [sorting](https://rv-grid.com/guide/sorting), [filtering](https://rv-grid.com/guide/filters), [column pinning](https://rv-grid.com/guide/column/pin), and [row pinning](https://rv-grid.com/guide/row/pin) cover common grid workflows. - The same [`` core](https://rv-grid.com/guide/defs#Web-Component) works across multiple frameworks. - Public [methods](https://rv-grid.com/guide/programmatic-control) and [events](https://rv-grid.com/guide/api/events) make it possible to build custom workflows without forking the grid. :::tip RevoGrid's [API](https://rv-grid.com/guide/api/revoGrid) is consistent across all major frameworks. Transfer your experience and knowledge from one framework to another. ::: :::warning Can't find your framework? [Ask us](https://github.com/revolist/revogrid/discussions) or [open an issue](https://github.com/revolist/revogrid/issues/new?assignees=&labels=&projects=&template=new-issue.md&title=) on GitHub. :::
Angular – Setup and usage in Angular environments.
React – Usage within React applications.
Dash / Python – Building data grids for Plotly Dash applications.
Svelte – Integrating into Svelte projects.
Vue 2 – Specific adaptations for Vue 2.
Vue 3 – Detailed guide for integrating with Vue 3.
# JavaScript Data Grid Demo Use this standalone JavaScript demo to see RevoGrid render editable tabular data with virtual scrolling and fast browser performance. :::preview #demo-overview .rv-overview :path /demo/js/js.overview.example ::: ::: details Source code [Git](https://github.com/revolist/revogrid-docs/tree/main/demo/js/js.overview.example.ts) [Codesandbox](https://codesandbox.io/p/sandbox/rg-quick-overview-88rf36?from-embed=) ::: code-group <<< @/demo/js/js.overview.example.ts#snippet <<< @/json/stock.json ::: ## Basic setup with a custom cell template RevoGrid can stay simple for read-only tables, or become interactive with custom renderers, editors, and events. This example adds a richer cell template while keeping the same grid setup: ```typescript // Snag your grid element from the DOM const grid = document.querySelector('revo-grid'); // Let the grid know about your columns and data grid.columns = [ { prop: 'first', name: 'First column' }, { prop: 'second', name: 'Second column', // Spice up your cell with a custom template cellTemplate: (h, { value }) => h('div', { style: { backgroundColor: 'red' }, // Because red is fast }, value || '') } ]; // Here's your data, ready to be displayed grid.source = [{ first: 'New item', second: 'Item description' //... Add more rows as needed }]; ``` ## Next steps Choose the path that matches what you are building: - [Installation](https://rv-grid.com/guide/installation): package managers, CDN usage, and loader setup. - [Get Pro Trial](https://rv-grid.com/trial): install the 30-day Pro trial and compare public demos before purchasing. - [Overview](https://rv-grid.com/guide/overview): how the grid is structured and when to use it. - [AI Agents and MCP](https://rv-grid.com/guide/mcp): connect Codex, Cursor, Claude Code, or VS Code to version-aware RevoGrid docs, examples, migrations, and typed API context. - [Filtering](https://rv-grid.com/guide/filters): enable built-in filtering and custom filter logic. - [Editing](https://rv-grid.com/guide/editing): inline editing, events, and read-only behavior. - [Understanding Viewports](https://rv-grid.com/guide/viewports): physical vs virtual indexes, pinned areas, and event coordinates. - [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control): methods such as `setDataAt`, `setCellEdit`, and `scrollToRow`. - [Advanced Configuration](https://rv-grid.com/guide/advanced-configuration): `columnTypes`, `rowDefinitions`, `trimmedRows`, `additionalData`, and plugin-oriented hooks. ## Framework guides If you are integrating RevoGrid into an application framework, start with the wrapper guide for your stack: - [TypeScript](https://rv-grid.com/guide/ts/) - [React](https://rv-grid.com/guide/react/) - [Angular](https://rv-grid.com/guide/angular/) - [Vue 3](https://rv-grid.com/guide/vue3/) - [Svelte](https://rv-grid.com/guide/svelte/) ## Example [![Edit RevoGrid - Quick Start](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/revogrid-60s-tlxgwn) --- # RevoGrid Installation Source: https://rv-grid.com/guide/installation Description: Install RevoGrid with npm, pnpm, yarn, bun, or a CDN, then register the Web Components loader for JavaScript or TypeScript projects. You can use RevoGrid in three common ways: - package manager installation for app projects - direct CDN usage for prototypes or no-build pages - framework wrappers for React, Angular, Vue, and Svelte If you are not sure where to start, use the package-manager flow and register the custom elements loader once in your application entrypoint. :::tip RevoGrid's [API](https://rv-grid.com/guide/api/revoGrid) is consistent across all major frameworks. Transfer your experience and knowledge from one framework to another. ::: :::warning Can't find your framework? [Ask us](https://github.com/revolist/revogrid/discussions) or [open an issue](https://github.com/revolist/revogrid/issues/new?assignees=&labels=&projects=&template=new-issue.md&title=) on GitHub. :::
Angular – Setup and usage in Angular environments.
React – Usage within React applications.
Dash / Python – Building data grids for Plotly Dash applications.
Svelte – Integrating into Svelte projects.
Vue 2 – Specific adaptations for Vue 2.
Vue 3 – Detailed guide for integrating with Vue 3.
## Install from a package manager Install the core package: ::: code-group ```npm npm i @revolist/revogrid ``` ```pnpm pnpm add @revolist/revogrid ``` ```yarn yarn add @revolist/revogrid ``` ```bun bun add @revolist/revogrid ``` ::: ## Register the Web Components loader RevoGrid ships as Web Components. Register them once before rendering any grid: ```ts import { defineCustomElements } from '@revolist/revogrid/loader'; defineCustomElements(); ``` This is the standard entrypoint for JavaScript and TypeScript applications. If you are using a framework wrapper, its own installation guide will show the package to install and the wrapper-specific setup. ## Minimal JavaScript or TypeScript setup Once the loader is registered, render the grid and assign data: ```ts const grid = document.querySelector('revo-grid'); grid.columns = [ { prop: 'name', name: 'Name' }, { prop: 'email', name: 'Email' }, ]; grid.source = [ { name: 'Ada Lovelace', email: 'ada@example.com' }, { name: 'Grace Hopper', email: 'grace@example.com' }, ]; ``` ## No-build integration For a quick proof of concept, load the grid directly from a CDN. ### Script tag ```html ``` ### ES modules ```html ``` Use the module version when you want to register the standalone custom element from an ES module. ## Which package should you install? - Core JavaScript/TypeScript: `@revolist/revogrid` - React wrapper: start at [React Data Grid](https://rv-grid.com/guide/react/) - Angular wrapper: start at [Angular Data Grid](https://rv-grid.com/guide/angular/) - Vue 3 wrapper: start at [Vue 3 Data Grid](https://rv-grid.com/guide/vue3/) - Svelte wrapper: start at [Svelte Data Grid](https://rv-grid.com/guide/svelte/) Evaluating Pro or Pro Advanced modules? Use [Get Pro Trial](https://rv-grid.com/trial) to install the 30-day trial, review public demos, and understand the path from evaluation to production. ## Common next steps - [Quick Start](https://rv-grid.com/guide/): first grid in plain JavaScript. - [TypeScript Data Grid](https://rv-grid.com/guide/ts/): typed columns and data models. - [Standalone and ES Modules](https://rv-grid.com/guide/standalone): framework-free module usage. - [SSR](https://rv-grid.com/guide/ssr): when the browser-only runtime affects your app shell. --- # JavaScript Data Grid Overview Source: https://rv-grid.com/guide/overview Description: Learn what RevoGrid provides for high-performance JavaScript data grids, including virtual scrolling, framework support, custom cells, editing, and large dataset workflows. So, you have an app that manages intensive datasets and you might think it’s straightforward enough to handle on your own. After all, implementing virtual scrolling might seem like all it takes. > But what happens when your needs grow? Suppose you want to [`pin`](https://rv-grid.com/guide/defs#Row-Pin-Freeze) a row at the top or bottom. [`Add a column`](https://rv-grid.com/guide/defs#Column) that also needs to be pinned. And then start [`grouping`](https://rv-grid.com/guide/defs#Row-Grouping) these elements. Soon, you might find yourself needing [`cell focus`](https://rv-grid.com/guide/defs#Focus) and [`range selections`](https://rv-grid.com/guide/defs#Range). This is where the complexity increases significantly. In scenarios like this, maintaining performance while adding sophisticated grid functionalities can become difficult.
## Motivation Confronted with vast data streams, we realized the limitations of existing solutions: while on-market 3rd-party libraries offered temporary respite, they came with their own set of challenges—prompting us to think beyond conventional method: > Our goal is to create a truly reactive datagrid core, one that could stand shoulder to shoulder with any framework while being universally accessible for developers and organizations alike. It's designed to handle the most demanding data without compromising on performance, ensuring that your applications run smoothly and efficiently. ## Magic behind the scene `RevoGrid` is built on top of [StencilJS](https://stenciljs.com/) (a compiler for building fast web apps using Web Components), leveraging the power of a reactive DOM to ensure optimal performance and responsiveness. Its architecture is *designed to handle large datasets* with ease, providing a seamless user experience even in data-intensive applications. This approach allows RevoGrid to be **framework-agnostic**, ensuring developers can integrate it into any project regardless of the underlying technology stack. ## VNode Reactive DOM At the core of RevoGrid's high performance is its use of a reactive DOM model (similar one you would find in any popular reactive framework [Vue Virtual DOM](https://vuejs.org/guide/extras/rendering-mechanism), [React Virtual DOM](https://legacy.reactjs.org/docs/faq-internals.html), etc.). This model ensures that only the parts of the grid that need updating are re-rendered, rather than the entire grid. This selective rendering mechanism is crucial for handling large amounts of data, as it significantly reduces the amount of DOM manipulation required, leading to smoother scrolling and interactions. ## Framework Native Support We have built native support for all popular frameworks, enabling you to integrate native elements directly inside the grid cells. For example, you can embed Vue/React/Angular components within RevoGrid, allowing for a rich and interactive data grid experience. To use native elements in your grid, simply utilize our providers. This feature enhances flexibility and allows you to leverage the unique capabilities of each framework while maintaining a unified grid experience. For more detailed information on implementing this functionality, be sure to read the relevant sections of our documentation. :::tip RevoGrid's [API](https://rv-grid.com/guide/api/revoGrid) is consistent across all major frameworks. Transfer your experience and knowledge from one framework to another. ::: :::warning Can't find your framework? [Ask us](https://github.com/revolist/revogrid/discussions) or [open an issue](https://github.com/revolist/revogrid/issues/new?assignees=&labels=&projects=&template=new-issue.md&title=) on GitHub. :::
Angular – Setup and usage in Angular environments.
React – Usage within React applications.
Dash / Python – Building data grids for Plotly Dash applications.
Svelte – Integrating into Svelte projects.
Vue 2 – Specific adaptations for Vue 2.
Vue 3 – Detailed guide for integrating with Vue 3.
## Why to choose? `RevoGrid` is an essential tool for developers aiming to build high-quality, data-intensive applications. RevoGrid distinguishes itself from other data grids with its unwavering commitment to user experience. Our `advanced scrolling` technology ensures seamless navigation through vast datasets—this finely tuned interaction is what sets us apart. Additionally, we support native behavior for `optimal out-of-browser performance` and features rapid cell rendering and updates, ensuring the application remains responsive at all times. These capabilities make us not just different, but superior in facilitating an efficient and smooth user interface. ::: info If you find yourself constantly pondering over questions like - Why is my application slowing down? - Should I enable paging to speed it up? - How can I manage such large volumes of data efficiently? - It looks like an Excel sheet; can it perform well? ::: Its highly competitive feature set and performance can be applied in various areas and industries. Here are our real-case scenarios where you can improve data management and user experience to a granular level. ## Where to apply? - ### Financial Modeling and Analysis Financial institutions and fintech startups can leverage RevoGrid for complex financial modeling and analysis. The grid's performance in handling large volumes of data, coupled with its support for custom cell formatting and editing, makes it ideal for real-time financial analysis, budgeting, and forecasting. - ### Project Management Tools Project management software can benefit from RevoGrid's capabilities to track tasks, deadlines, and progress across multiple projects. The grid's flexibility and performance make it suitable for creating detailed project dashboards that enhance team collaboration and efficiency. - ### E-Commerce Dashboards E-commerce platforms can use RevoGrid to manage large inventories, track orders, and analyze customer data. The grid's efficient data rendering and manipulation capabilities allow for real-time updates and seamless user interactions, crucial for monitoring sales trends and inventory levels. - ### Healthcare Data Management Healthcare applications can benefit from RevoGrid's ability to handle large datasets, such as patient records, appointment schedules, and treatment histories. The grid's sorting, filtering, and editing features enable healthcare professionals to quickly access and manage patient information, improving the efficiency of care delivery. - ### Educational Platforms Educational software, including learning management systems (LMS), can use RevoGrid to display and manage student data, course materials, and grades. The grid's customizable nature allows for the creation of intuitive interfaces that cater to the diverse needs of educators and students. - ### Real Estate Portals Real estate platforms can utilize RevoGrid to display property listings, including detailed information such as images, descriptions, prices, and agent contacts. The grid's virtual scrolling and efficient data rendering ensure a smooth user experience, even with thousands of listings. - ### Logistics and Supply Chain Management For logistics and supply chain applications, RevoGrid can manage and display shipping schedules, inventory levels, and transport routes. Its high performance and dynamic data manipulation capabilities support the complex, real-time data needs of logistics operations. ## Find guides for your framework :::tip RevoGrid's [API](https://rv-grid.com/guide/api/revoGrid) is consistent across all major frameworks. Transfer your experience and knowledge from one framework to another. ::: :::warning Can't find your framework? [Ask us](https://github.com/revolist/revogrid/discussions) or [open an issue](https://github.com/revolist/revogrid/issues/new?assignees=&labels=&projects=&template=new-issue.md&title=) on GitHub. :::
Angular – Setup and usage in Angular environments.
React – Usage within React applications.
Dash / Python – Building data grids for Plotly Dash applications.
Svelte – Integrating into Svelte projects.
Vue 2 – Specific adaptations for Vue 2.
Vue 3 – Detailed guide for integrating with Vue 3.
--- # Data Source Loading and Syncing Source: https://rv-grid.com/guide/data-sync Description: Choose how RevoGrid should receive, own, and synchronize row data across JavaScript, TypeScript, React, Vue, Angular, and Svelte applications. When you work with any JS Data Grid or complex component, most of the time the framework changes, but the data question is the same: > Who owns the edited data? Once that is clear, integration becomes much easier. ## Start with ownership | Approach | What it means | Use it when | | --- | --- | --- | | Grid-owned data | RevoGrid edits the row objects passed to `source` | The grid is a local draft, import tool, spreadsheet, or save-on-submit UI | | App-owned data | Your store or server model owns the final value | Other screens, validation, autosave, audit logs, or collaboration need the edits | Both approaches work. Problems usually start when a reactive app replaces the whole grid source after every edit: ```txt cell edit -> app state update -> new source array -> grid receives a new dataset ``` That looks natural in many frameworks, but it is expensive for a virtual grid. A new `source` is treated as a dataset-level change. It can reset or disturb selection, focus, editor state, scroll position, history, dirty tracking, and plugin state. For normal editing, keep the active `source` stable and sync only the changed value. ## How editing works RevoGrid reads and writes the row objects in `source`. ```ts const source = [ { id: 1, name: 'Apple', price: 1.2 }, { id: 2, name: 'Banana', price: 0.5 }, ]; grid.source = source; grid.columns = [ { prop: 'name', name: 'Name' }, { prop: 'price', name: 'Price' }, ]; ``` If a user edits the first row price, the same row object receives the new `price`. RevoGrid does not need a fresh array just to show that edit. ## Option 1: Let the grid own the draft This is the simplest model. Pass rows to the grid, let users edit, and read the data when you need to save. ```ts grid.source = source; async function save() { const rows = await grid.getSource(); await saveRows(rows); } ``` Use this when the rest of the app does not need to react immediately to every cell edit. ## Option 2: Listen after edits Use `afteredit` when the grid should apply the edit first, then your app should hear about the changed field. ```ts grid.addEventListener('afteredit', event => { const { model, prop, val } = event.detail; updateStore(model.id, prop, val); }); ``` This should be an incremental sync. Do not immediately rebuild `source` from the store and pass it back to the grid for the same edit. Use `beforeedit` or `beforerangeedit` when you need to block or normalize a value before it is saved: ```ts grid.addEventListener('beforeedit', event => { if (event.detail.prop === 'price' && Number(event.detail.val) < 0) { event.preventDefault(); } }); ``` ## Option 3: Use a proxy source A proxy source is useful when your store must see writes immediately, but RevoGrid still needs stable row objects. ```ts function createRowProxy(row, updateStore) { return new Proxy(row, { set(target, prop, value) { Reflect.set(target, prop, value); updateStore(target.id, prop, value); return true; }, }); } grid.source = rows.map(row => createRowProxy(row, updateStore)); ``` The flow is: ```txt cell edit -> proxy setter -> app store ``` Create proxies once for the active dataset. Do not create a new proxy array on every render. For the full pattern, see [Proxy Source Editing](https://rv-grid.com/guide/proxy-source). ## Option 4: Keep a patch layer Use patches when you want dirty tracking, review-before-save, validation flows, or batch submit. ```ts const patches = {}; grid.addEventListener('afteredit', event => { const { model, prop, val } = event.detail; patches[model.id] ??= {}; patches[model.id][prop] = val; }); function getResolvedValue(row, prop) { return patches[row.id]?.[prop] ?? row[prop]; } ``` This keeps the grid data stable while your app tracks the changes separately. ## Option 5: Batch external sync Use a queue when edits should go to a store, API, or analytics pipeline, but not one by one. ```ts const queue = []; let flushTimer = 0; grid.addEventListener('afteredit', event => { queue.push(event.detail); scheduleFlush(); }); function scheduleFlush() { if (!flushTimer) { flushTimer = window.setTimeout(flush, 250); } } function flush() { flushTimer = 0; updateStoreBatch(queue.splice(0)); } ``` This works well for autosave, paste, fill, and high-volume editing. ## Framework notes Different frameworks express reactivity differently, but the practical rule stays the same: stable grid inputs, incremental edit sync. | Environment | Prefer | Avoid | | --- | --- | --- | | JavaScript / TypeScript | Create `source` once for the active dataset | Reassigning `grid.source` after every edit | | React | Keep active rows in `useMemo`, `useRef`, or a store adapter | Creating a fresh `source` from `setState` on each `afteredit` | | Vue | Use stable state, `shallowRef`, or a store adapter | Deep reactive churn that rebuilds row objects | | Angular | Keep `source` as a stable field, signal value, or adapter result | Replacing `[source]` every time `(afteredit)` fires | | Svelte | Keep the array reference stable or sync through a store adapter | Reassigning the `source` prop for each edited cell | Reactive UI state is good for screens. RevoGrid also has viewport, focus, editing, and plugin state. Treat full `source` replacement as loading a dataset, not as the default way to handle a cell edit. ## Replace `source` when the dataset changes Full replacement is correct for: - initial load - page change - dataset switch - server refresh - filter or search result replacement - server-side pagination, sorting, filtering, or grouping result replacement - adding, removing, or reordering rows outside the grid - switching from draft data to confirmed server data For targeted cell changes from application code, use methods such as `setDataAt` from [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control). For live streams, see [Real-Time Updates in RevoGrid](https://rv-grid.com/guide/realtime-updates). ## Quick checklist - Decide whether the grid or the app owns edits. - Keep `source` and `columns` stable while editing. - Use `afteredit` for post-edit sync. - Use `beforeedit` or `beforerangeedit` for validation or cancellation. - Use proxy, patch, or queue patterns when the app needs more control. - Replace the full source only when the dataset itself changes. ## Rule of thumb Good: ```txt cell edit -> afteredit/proxy/patch/queue -> incremental app sync ``` Problematic: ```txt cell edit -> recreate full source -> grid receives new dataset ``` ## Related guides - [Proxy Source Editing](https://rv-grid.com/guide/proxy-source) - [State Persistence](https://rv-grid.com/guide/state-persistence) - [Server-side data, pagination, sorting, and filtering](https://rv-grid.com/guide/server-side-data) - [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control) - [RevoGrid Event Patterns and Lifecycles](https://rv-grid.com/guide/events-guide) - [Real-Time Updates in RevoGrid](https://rv-grid.com/guide/realtime-updates) - [RevoGrid Best Practices](https://rv-grid.com/guide/patterns) --- # RevoGrid State Persistence Source: https://rv-grid.com/guide/state-persistence Description: Save and restore RevoGrid user state including column order, column width, pinned columns, sorting, filtering, selection, scroll position, layout presets, and Pro workspace state. Grid users expect their workspace to survive reloads, device switches, saved views, and product releases. Common state includes column order, widths, pinned columns, sorting, filters, selection, scroll position, grouping, pivot fields, Gantt preferences, and named layout presets. RevoGrid keeps this practical: your application owns the persisted state, and RevoGrid exposes the props, methods, and events needed to collect and restore it. Instead of relying on one monolithic `getGridState()` object, persist the pieces your product actually supports. ## What to persist Start with a small state object and extend it as users need more saved workspace behavior. ```ts type PersistedFilterState = { collection: Record< string, { type: | 'empty' | 'notEmpty' | 'eq' ...; value: unknown; } >; }; type PersistedGridState = { version: 1; schema: string; columnOrder: string[]; columnWidths: Record; pinnedColumns: { start: string[]; end: string[]; }; sorting?: { columns?: { prop: string; order: 'asc' | 'desc'; }[]; }; filter?: PersistedFilterState; selection?: { x: number; y: number; x1: number; y1: number; } | null; scroll?: { row?: number; columnProp?: string; }; grouping?: unknown; pivot?: unknown; gantt?: unknown; preferences?: { density?: 'compact' | 'comfortable'; theme?: string; }; layoutPreset?: string; }; ``` Use stable column `prop` values as the durable identifiers. Avoid persisting virtual indexes as the primary state because indexes change when columns are reordered, pinned, hidden, filtered, or replaced. ## Save to localStorage This example stores column order, sorting, filtering, selection, and scroll state. It keeps the shape app-owned so you can add product-specific preferences later. :::preview #demo-state-persistence .rv-overview :path /demo/js/js.state-persistence.example ::: :::: details Source code [Git](https://github.com/revolist/revogrid-docs/tree/main/demo/js/js.state-persistence.example.ts) ::: code-group <<< @/demo/js/js.state-persistence.example.ts#snippet ::: :::: ## Restore on page load Restore structural state before assigning `columns`, then restore scroll and selection after the grid has rendered. ```ts function applyPersistedColumns(columns, state) { if (!state) { return columns; } const order = new Map( (state.columnOrder ?? []).map((prop, index) => [prop, index]), ); const sorting = new Map( (state.sorting?.columns ?? []).map(column => [ String(column.prop), column.order, ]), ); return [...columns] .map(column => ({ ...column, size: state.columnWidths?.[String(column.prop)] ?? column.size, pin: getPersistedPin(column.prop, state), order: sorting.get(String(column.prop)), })) .sort((a, b) => { const left = order.get(String(a.prop)) ?? Number.MAX_SAFE_INTEGER; const right = order.get(String(b.prop)) ?? Number.MAX_SAFE_INTEGER; return left - right; }); } function getPersistedPin(prop, state) { const key = String(prop); if (state.pinnedColumns?.start?.includes(key)) { return 'colPinStart'; } if (state.pinnedColumns?.end?.includes(key)) { return 'colPinEnd'; } return undefined; } async function restoreViewport(grid, state) { if (state?.scroll?.row !== undefined) { await grid.scrollToRow(state.scroll.row); } if (state?.scroll?.columnProp) { await grid.scrollToColumnProp(state.scroll.columnProp); } if (state?.selection) { await grid.setCellsFocus( { x: state.selection.x, y: state.selection.y }, { x: state.selection.x1, y: state.selection.y1 }, ); } } ``` For scroll restoration, prefer row ids or business cursors when your dataset changes often. Numeric row coordinates are useful for restoring a viewport in the same dataset, but they may point to different records after server refreshes, filtering, or row insertion. ## Save to a backend Use the same state object for backend persistence. Debounce writes so resize, scroll, filtering, and drag operations do not create excessive requests. ```ts let saveTimer = 0; let pendingState = {}; function queueBackendState(partial) { pendingState = { ...pendingState, ...partial }; window.clearTimeout(saveTimer); saveTimer = window.setTimeout(async () => { const body = { gridId: 'orders', state: { version: 1, schema: createSchemaKey(baseColumns), ...loadGridState(), ...pendingState, }, }; pendingState = {}; await fetch('/api/grid-state/orders', { method: 'PUT', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body), }); }, 400); } grid.addEventListener('filterconfigchanged', event => { queueBackendState({ filter: event.detail }); }); grid.addEventListener('sortingconfigchanged', event => { queueBackendState({ sorting: event.detail }); }); ``` Backend state should be scoped by user, tenant, product area, grid id, and layout preset. Keep row data and workspace state separate: row edits belong in your data model, while grid state belongs in user preferences. ## Handle schema changes Persisted state lasts longer than one release. Version it, store a schema key, and ignore state for columns that no longer exist. ```ts function createSchemaKey(columns) { return columns.map(column => String(column.prop)).sort().join('|'); } function normalizeStateForColumns(state, columns) { if (!state) { return null; } const validProps = new Set(columns.map(column => String(column.prop))); return { ...state, schema: createSchemaKey(columns), columnOrder: (state.columnOrder ?? []).filter(prop => validProps.has(prop)), columnWidths: Object.fromEntries( Object.entries(state.columnWidths ?? {}).filter(([prop]) => validProps.has(prop), ), ), pinnedColumns: { start: (state.pinnedColumns?.start ?? []).filter(prop => validProps.has(prop), ), end: (state.pinnedColumns?.end ?? []).filter(prop => validProps.has(prop), ), }, }; } ``` New columns should fall back to your default column definitions. Removed columns should be dropped from persisted order, width, pinning, sorting, filtering, and presets. ## Version persisted state Use a version number when state can outlive a release. Migrate old shapes at load time and save the new shape after a successful restore. ```ts function migrateGridState(state) { if (!state) { return null; } if (state.version === 1) { return state; } if (state.version === undefined) { return { version: 1, schema: state.schema ?? '', columnOrder: state.columns ?? [], columnWidths: state.widths ?? {}, pinnedColumns: { start: state.pinnedStart ?? [], end: state.pinnedEnd ?? [], }, sorting: state.sorting, filter: state.filter, }; } return null; } ``` If migration fails, discard the saved state for that grid and load the default layout. A broken preference should not block users from opening the grid. ## Pro and advanced state Persist advanced feature state the same way: keep the plugin or feature config in your application state, save the user-controlled parts, and restore them before rendering the grid. | Feature | Persist | | --- | --- | | Row grouping | Grouping props, expanded groups, and user-selected grouping presets. | | Tree data | Expanded row ids and hierarchy display preferences. | | Pivot | Rows, columns, values, filters, aggregations, subtotals, grand totals, drill-down or expanded paths, and selected report preset. | | Gantt | Timeline scale, visible date window, task columns, collapsed task groups, dependency visibility, resource filters, and scheduling preferences. | | Layout presets | A named collection of columns, sorting, filters, plugin config, and product-specific preferences. | Do not mix persisted workspace state with editable business data. For example, Gantt task dates, dependencies, and assignments usually belong in your project data API. The user's preferred timeline zoom or visible columns belong in grid state. ## Quick checklist - Use stable column `prop` values. - Persist only state your product can restore. - Restore columns, pinning, filters, and sorting before viewport state. - Restore scroll and selection after the grid is ready. - Debounce backend saves. - Version saved state and migrate or discard old shapes. - Drop state for columns that no longer exist. - Keep row data synchronization separate from workspace preferences. ## Related guides - [Data Source Loading and Syncing](https://rv-grid.com/guide/data-sync) - [Column Ordering](https://rv-grid.com/guide/column/order) - [Column Pinning](https://rv-grid.com/guide/column/pin) - [Filtering](https://rv-grid.com/guide/filters) - [Data Grid Sorting](https://rv-grid.com/guide/sorting) - [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control) - [Understanding Viewports](https://rv-grid.com/guide/viewports) - [RevoGrid Pivot](https://rv-grid.com/pivot/) - [RevoGrid Gantt](https://rv-grid.com/gantt/) --- # Data Grid Width/Height Source: https://rv-grid.com/guide/grid.size # Data Grid Width/Height Working with other data grid systems you probably looking for a way to setup width or height for grid viewport. Good news it'll be updated automatically. All you have todo just change size of your table with css. Be aware that there is a min-height of `300px` in the default data grid. It's just to avoid the grid to be too small. --- # RevoGrid Best Practices Source: https://rv-grid.com/guide/patterns Description: Learn the practical patterns that keep RevoGrid fast and maintainable, including virtualization-safe renderers, state handling, editing flows, and large dataset strategies. RevoGrid is designed for large datasets and interactive workflows, but the best results still come from using the right patterns. This guide focuses on practices that align with how the grid actually renders, edits, filters, and updates data. ## Treat virtualization as the default The core grid renders only the visible rows and columns plus a small frame around them. Build with that assumption: - keep custom cell renderers light - avoid expensive DOM work per cell - avoid doing data transforms inside every render callback - prefer precomputed values on the row model when a template is reused many times Read more in [Grid Performance and Virtualization](https://rv-grid.com/guide/performance). ## Separate source data from presentation concerns Keep your source rows focused on business data, and use column config for presentation: - `columns` define names, sorting, filters, templates, editors, and read-only rules - `columnTypes` let you reuse configuration across many columns - `rowDefinitions` are better than mutating row height logic into templates - `additionalData` is useful for integration context, not as a second source of row data ## Prefer simple renderers first Custom renderers are one of RevoGrid’s strengths, but the safest progression is: 1. plain column values 2. `cellProperties` for classes and attributes 3. `cellTemplate` for custom rendering 4. framework-native renderers only when the feature truly needs them That keeps scroll performance predictable and makes debugging easier. ## Use stable keys in dynamic VNode output When a renderer returns multiple nodes or list content, use stable keys based on your data model rather than array position. This helps the underlying VDOM reconcile updates correctly during filtering, sorting, and scrolling. ## Use methods for imperative workflows If the UI needs to: - focus a cell - open an editor - scroll to a row or column - update a visible cell without rebuilding the whole grid use the public methods instead of custom DOM hacks. Start with [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control). ## Keep event handling intentional RevoGrid emits many events. In application code, it helps to group them by purpose: - validation and write control: `beforeedit`, `beforerangeedit`, `beforeeditstart` - source synchronization: `beforesourceset`, `aftersourceset`, `afteranysource` - filtering and sorting pipelines: `beforefilterapply`, `beforefiltertrimmed`, `beforesorting` - focus and selection: `beforecellfocus`, `beforefocuslost`, `afterfocus` Use cancelable events to enforce business rules and informative events for analytics, syncing, or UI side effects. Read more in [Event Patterns and Lifecycles](https://rv-grid.com/guide/events-guide). ## Use physical and virtual indexes correctly A common source of bugs is mixing physical source indexes with viewport indexes: - source arrays are physical data - event coordinates are often viewport-specific virtual indexes - pinned rows and columns create separate index spaces If you are using `setDataAt`, `setCellsFocus`, custom plugins, or advanced event handling, read [Understanding Viewports](https://rv-grid.com/guide/viewports). ## Choose the right loading strategy For large or remote datasets: - use built-in virtualization first - use filtering and sorting carefully if the dataset must stay server-authoritative - use incremental loading or pagination patterns when you do not want the full dataset in memory - use `jobsBeforeRender` for initialization work that must finish before the first meaningful paint For a complete remote data pattern with pagination, sorting, filtering, cancellation, caching, and optimistic edits, read [Server-side data, pagination, sorting, and filtering](https://rv-grid.com/guide/server-side-data). ## Keep editing rules close to the column Editing behavior is easiest to maintain when it is defined where the user sees it: - `readonly` at grid or column level for broad rules - custom editors in `editors` - `applyOnClose` when you want close-to-save behavior - validation in `beforeedit` or related hooks Read more in [Editing](https://rv-grid.com/guide/editing). ## Make framework wrappers thin Whether you use React, Angular, Vue 3, or Svelte, keep the wrapper layer focused on: - providing props and events - holding refs to the grid instance - passing framework context through `additionalData` only when needed The more business logic stays close to the shared RevoGrid API, the easier it is to keep behavior consistent across frameworks. ## Related guides - [Grid Performance and Virtualization](https://rv-grid.com/guide/performance) - [Server-side data, pagination, sorting, and filtering](https://rv-grid.com/guide/server-side-data) - [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control) - [Advanced Configuration](https://rv-grid.com/guide/advanced-configuration) - [Editing](https://rv-grid.com/guide/editing) - [Filtering](https://rv-grid.com/guide/filters) --- # RevoGrid Performance and Virtualization Source: https://rv-grid.com/guide/performance Description: Learn how RevoGrid keeps large datasets fast with virtual rendering, frame sizing, viewport settings, and initialization strategies such as jobsBeforeRender. RevoGrid is designed to stay responsive with large datasets by rendering only what is needed. This guide explains the main performance-related props and when to use them. ## Virtual rendering is the default The grid renders: - visible rows and columns - a small buffer outside the viewport - pinned regions in coordinated viewports This is why large datasets stay fast as long as cell templates and event handlers stay lightweight. In practice, performance problems usually come from custom application code, not from the base grid itself. The most common causes are: - expensive cell templates - rebuilding `columns` too often - pushing too much logic into per-cell render functions - forcing full rerenders when a targeted update would be enough ## `frameSize` `frameSize` defines how many extra rows and columns are rendered outside the visible area. ```ts grid.frameSize = 1; ``` Use a higher value if: - users scroll very quickly - custom cells are visually expensive to mount - you want a slightly larger pre-render buffer Use a lower value if: - you want to minimize off-screen rendering - your templates are already cheap Starting point: - `1` is a good default for most apps - increase it gradually if you see visible blanking during very fast scrolls ## `disableVirtualX` `disableVirtualX` disables lazy rendering for columns. ```ts grid.disableVirtualX = true; ``` This can help when: - the grid has only a small number of columns - you prefer stable DOM for horizontally visible cells - initial rendering is more important than horizontal virtualization Do not enable it by default for wide grids. Example: ```ts grid.disableVirtualX = grid.columns.length < 10; ``` ## `disableVirtualY` `disableVirtualY` disables lazy rendering for rows. ```ts grid.disableVirtualY = true; ``` This is only appropriate when the row count is small enough that full vertical rendering is affordable. Example: ```ts grid.disableVirtualY = grid.source.length < 100; ``` ## `jobsBeforeRender` `jobsBeforeRender` lets you defer the first meaningful render until required async work is ready. ```ts grid.jobsBeforeRender = [ fetch('/api/schema').then(r => r.json()), fetch('/api/initial-grid-state').then(r => r.json()), ]; ``` Good use cases: - schema or permissions that must load before columns are built - plugin bootstrapping that would otherwise cause immediate double rendering - initial app state that must exist before the first visible grid Typical setup: ```ts const schemaJob = fetch('/api/columns').then(r => r.json()); const settingsJob = fetch('/api/grid-settings').then(r => r.json()); grid.jobsBeforeRender = [schemaJob, settingsJob]; ``` ## Renderer performance tips - keep `cellTemplate` work small - avoid network requests from inside renderers - avoid rebuilding large arrays or objects on every cell render - prefer data precomputation before assigning `source` Bad pattern: ```ts cellTemplate: () => { const expensive = largeArray.filter(x => x.active); return h('div', expensive.length); } ``` Better pattern: ```ts const activeCount = largeArray.filter(x => x.active).length; cellTemplate: () => h('div', activeCount) ``` ## Update methods for smoother UX When you need to update a specific visible cell, `setDataAt` is often cheaper than rebuilding the entire grid state from scratch. See [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control). ## Performance checklist - use plain values before custom templates - keep row data normalized before it reaches the grid - prefer `setDataAt` for targeted updates - use `getVisibleSource()` when operations only need the currently visible rows - use server-side pagination, filtering, sorting, or grouping when the full dataset should not live in the browser - leave virtualization enabled unless the dataset is genuinely small ## Related guides - [Benchmarks](https://rv-grid.com/benchmarks) - [Understanding Viewports](https://rv-grid.com/guide/viewports) - [Server-side data, pagination, sorting, and filtering](https://rv-grid.com/guide/server-side-data) - [Best Practices](https://rv-grid.com/guide/patterns) - [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control) - [API: RevoGrid](https://rv-grid.com/guide/api/revoGrid) --- # Programmatic Grid Control Source: https://rv-grid.com/guide/programmatic-control Description: Control RevoGrid from application code with public methods for editing, focus, scrolling, visible source access, and targeted cell updates. RevoGrid exposes a rich public method surface for workflows driven by toolbars, external forms, keyboard shortcuts, or business logic. ## Get a grid instance In plain JavaScript: ```ts const grid = document.querySelector('revo-grid'); ``` In framework wrappers, use the wrapper-specific ref or element access pattern, then call the underlying grid methods. Example toolbar action: ```ts const editFirstRowBtn = document.querySelector('#edit-first-row'); const grid = document.querySelector('revo-grid'); editFirstRowBtn?.addEventListener('click', async () => { await grid?.scrollToRow(0); await grid?.setCellEdit(0, 'name'); }); ``` ## Update one cell with `setDataAt` Use `setDataAt` when you want to update a specific visible cell and refresh that cell without rebuilding the full grid. ```ts await grid.setDataAt({ row: 0, col: 0, val: 'Updated', }); ``` Example with explicit viewport types: ```ts await grid.setDataAt({ row: 0, col: 0, rowType: 'rowPinStart', colType: 'rgCol', val: 'Pinned row value', }); ``` Notes: - `row` and `col` are virtual coordinates inside the selected viewport - `rowType` defaults to `rgRow` - `colType` defaults to `rgCol` - `skipDataUpdate` can skip source mutation if you are only refreshing the rendered cell ## Open an editor with `setCellEdit` ```ts await grid.setCellEdit(0, 'price'); ``` This is useful when an external button or shortcut should put the user directly into editing mode. Example with pinned rows: ```ts await grid.setCellEdit(0, 'status', 'rowPinStart'); ``` ## Move focus with `setCellsFocus` ```ts await grid.setCellsFocus({ x: 0, y: 0 }, { x: 2, y: 4 }); ``` You can focus a single cell or a multi-cell range. Focus a single cell before editing: ```ts await grid.setCellsFocus({ x: 1, y: 3 }, { x: 1, y: 3 }); await grid.setCellEdit(3, 'price'); ``` ## Clear focus and inspect the current range ```ts await grid.clearFocus(); const range = await grid.getSelectedRange(); console.log(range); ``` Typical pattern: ```ts const range = await grid.getSelectedRange(); if (range) { console.log('Selected area', range.x, range.y, range.x1, range.y1); } ``` ## Scroll to content Scroll by row index: ```ts await grid.scrollToRow(100); ``` Scroll by column index: ```ts await grid.scrollToColumnIndex(5); ``` Scroll by column `prop`: ```ts await grid.scrollToColumnProp('status'); ``` This is usually safer than using column indexes when columns can be reordered or grouped. ## Read visible rows ```ts const visibleRows = await grid.getVisibleSource(); ``` Use this when your app should work with the rows currently visible after trimming, filtering, or sorting. Example: ```ts const visibleRows = await grid.getVisibleSource(); const selectedEmails = visibleRows.map(row => row.email); console.log(selectedEmails); ``` ## Read source and stores ```ts const source = await grid.getSource(); const rowStore = await grid.getSourceStore(); const colStore = await grid.getColumnStore(); ``` The store methods are mainly for advanced integrations and plugin work. If you only need the current displayed rows, prefer `getVisibleSource()` over reading the raw store. ## Update sorting from application code ```ts await grid.updateColumnSorting({ prop: 'name' }, 'asc', false); await grid.clearSorting(); ``` This emits the sorting configuration change rather than mutating the source directly. Multi-step example: ```ts await grid.updateColumnSorting({ prop: 'status' }, 'asc', false); await grid.updateColumnSorting({ prop: 'createdAt' }, 'desc', true); ``` The second call keeps the first sort because `additive` is `true`. ## Plugin-oriented methods These methods are most useful in advanced integrations: - `getPlugins()` - `getProviders()` - `refreshExtraElements()` They give access to active plugins and provider services used internally by the grid. ## Common patterns ### Build a “go to row” action ```ts async function goToRow(rowIndex) { await grid.scrollToRow(rowIndex); await grid.setCellsFocus({ x: 0, y: rowIndex }, { x: 0, y: rowIndex }); } ``` ### Refresh a visible cell after an external update ```ts async function updateStatusCell(row, nextValue) { await grid.setDataAt({ row, col: 2, val: nextValue, }); } ``` ### Read the filtered view before export or bulk action ```ts const filteredRows = await grid.getVisibleSource(); console.log(`Exporting ${filteredRows.length} visible rows`); ``` ## Related guides - [Understanding Viewports](https://rv-grid.com/guide/viewports) - [Advanced Configuration](https://rv-grid.com/guide/advanced-configuration) - [Event Patterns and Lifecycles](https://rv-grid.com/guide/events-guide) - [API: RevoGrid](https://rv-grid.com/guide/api/revoGrid) --- # Proxy Source Editing Source: https://rv-grid.com/guide/proxy-source Description: Use JavaScript Proxy row models with RevoGrid so edits write through to an application-owned data store without edit event handlers. RevoGrid reads and writes the row objects passed through `source`. During a normal edit, RevoGrid gets the row model for the visible row, assigns the edited value to `model[prop]`, and refreshes the source view. You can use this behavior to make the application store the source of truth. Instead of listening to `beforeedit`, `beforerangeedit`, or `afteredit` for every write, pass RevoGrid an array of proxied row models. The proxy intercepts property reads and writes: - `get` returns the value RevoGrid should render, sort, filter, group, or edit. - `set` writes the new value into your application store. - the same proxy row stays in `grid.source`, so RevoGrid keeps working with normal row objects. Use edit events when you need grid-level cancellation, editor lifecycle control, analytics, or UI feedback. Use a proxy source when the main goal is to route cell writes into your own model. ## Basic Proxy Source This example keeps `rawRows` as the application-owned data and passes a proxied array to RevoGrid. ```ts type ProductRow = { id: number; name: string; price: number; status: 'draft' | 'published'; }; const rawRows: ProductRow[] = [ { id: 1, name: 'Apple', price: 1.2, status: 'draft' }, { id: 2, name: 'Banana', price: 0.5, status: 'published' }, ]; function syncChange(row: ProductRow, prop: keyof ProductRow, value: unknown) { console.log('row changed', row.id, prop, value); } function createRowProxy( row: T, onWrite: (row: T, prop: keyof T, value: unknown) => void, ): T { return new Proxy(row, { get(target, prop, receiver) { return Reflect.get(target, prop, receiver); }, set(target, prop, value) { Reflect.set(target, prop, value); onWrite(target, prop as keyof T, value); return true; }, }); } const proxySource = rawRows.map(row => createRowProxy(row, syncChange)); const grid = document.querySelector('revo-grid'); if (grid) { grid.columns = [ { prop: 'id', name: 'ID', readonly: true }, { prop: 'name', name: 'Name' }, { prop: 'price', name: 'Price' }, { prop: 'status', name: 'Status' }, ]; grid.source = proxySource; } ``` When a user edits the `price` cell, RevoGrid writes to the proxied row. The proxy updates `rawRows` and calls `syncChange`. ## External Store A proxy source is useful when the grid-facing row shape is not the same as your store access pattern. This example stores rows by ID, tracks dirty fields, and queues asynchronous saves. ```ts type InventoryRow = { id: string; sku: string; quantity: number; location: string; }; const rowsById = new Map([ ['a1', { id: 'a1', sku: 'A-001', quantity: 10, location: 'Lisbon' }], ['b2', { id: 'b2', sku: 'B-002', quantity: 25, location: 'Porto' }], ]); const dirtyFields = new Map>(); const saveQueue: InventoryRow[] = []; function markDirty(id: string, prop: keyof InventoryRow) { const fields = dirtyFields.get(id) ?? new Set(); fields.add(prop); dirtyFields.set(id, fields); } function queueSave(row: InventoryRow) { saveQueue.push({ ...row }); } function createStoreRowProxy(id: string): InventoryRow { return new Proxy({ id } as InventoryRow, { get(_, prop) { return rowsById.get(id)?.[prop as keyof InventoryRow]; }, set(_, prop, value) { const row = rowsById.get(id); if (!row) { return false; } (row as Record)[prop] = value; markDirty(id, prop as keyof InventoryRow); queueSave(row); return true; }, }); } const proxySource = [...rowsById.keys()].map(createStoreRowProxy); grid.source = proxySource; grid.columns = [ { prop: 'sku', name: 'SKU', readonly: true }, { prop: 'quantity', name: 'Quantity' }, { prop: 'location', name: 'Location' }, ]; ``` The proxy object exposes normal row properties to RevoGrid, but every read comes from `rowsById` and every write goes back into `rowsById`. ## Validation and Normalization The `set` trap can normalize values before they reach your store. ```ts function createValidatedRowProxy(row: ProductRow): ProductRow { return new Proxy(row, { set(target, prop, value) { if (prop === 'name') { target.name = String(value).trim(); return true; } if (prop === 'price') { const price = Number(value); if (!Number.isFinite(price) || price < 0) { // Soft reject: keep the previous value and let the grid refresh it. return true; } target.price = price; return true; } Reflect.set(target, prop, value); return true; }, }); } ``` Returning `false` from a proxy `set` trap rejects the JavaScript assignment. In strict-mode code this can throw a `TypeError`, so a soft reject that preserves the previous value is usually easier for grid editing flows. If the editor must be blocked before the value is committed, use `beforeedit` or `beforerangeedit` instead. Those events are still the correct place for hard cancellation and user-facing validation messages. ## Range Edits, Paste, and Programmatic Writes Range edits and paste operations update row models by assigning values to the edited column properties. With a proxy source, those assignments still pass through the row proxy. Programmatic writes use the same data path unless you explicitly skip data updates: ```ts await grid.setDataAt({ row: 0, col: 1, val: 'Updated name', }); ``` If you call `setDataAt` with `skipDataUpdate: true`, RevoGrid updates the rendered cell only and does not assign the value into the row model. ```ts await grid.setDataAt({ row: 0, col: 1, val: 'Temporary render value', skipDataUpdate: true, }); ``` ## Refresh Rules If a grid edit writes through the proxy and the proxy returns the new value from the same row object, the normal edit flow updates the visible cell. When the application store changes outside RevoGrid, refresh the grid so visible cells read the latest values from the proxies: ```ts rowsById.get('a1')!.quantity = 12; await grid.refresh(); ``` If rows are added, removed, or reordered outside the grid, rebuild the proxied source array and assign it again: ```ts const proxySource = [...rowsById.keys()].map(createStoreRowProxy); grid.source = proxySource; ``` Pinned rows use separate sources, so prepare separate proxied arrays for them: ```ts grid.pinnedTopSource = topRows.map(row => createRowProxy(row, syncChange)); grid.pinnedBottomSource = summaryRows.map(row => createRowProxy(row, syncChange), ); ``` ## Practical Rules - Keep proxy object identity stable where possible. - Do not create proxies inside framework render loops. Build them in state setup, memoization, computed state, or a store adapter. - Do not mutate the same field through both a proxy source and edit event handlers unless that duplication is intentional. - Sorting, filtering, grouping, and cell rendering use values returned by the proxy `get` trap. - Use `readonly`, `beforeedit`, and `beforerangeedit` for hard edit rules. Use proxy `set` for store synchronization and normalization. ## Related Guides - [Data Source Loading and Syncing](https://rv-grid.com/guide/data-sync) - [Editing](https://rv-grid.com/guide/editing) - [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control) - [Event Patterns and Lifecycles](https://rv-grid.com/guide/events-guide) --- # RevoGrid MCP for AI Agents Source: https://rv-grid.com/guide/mcp Description: Connect Codex, Cursor, Claude Code, and VS Code to the RevoGrid MCP server for version-aware docs, examples, migration notes, and typed API context. RevoGrid MCP gives AI coding tools a structured way to work with RevoGrid instead of guessing from stale training data. It exposes version-aware documentation, runnable examples, migration notes, feature availability, and typed API context in a format that agents can query directly. This is especially useful when you want an AI tool to: - start from a working RevoGrid example instead of inventing setup code - verify whether a feature exists in Core or Pro before suggesting it - use current event names, options, and types such as `ColumnRegular` or `BeforeEdit` - follow migration guidance between RevoGrid versions ## What the MCP server provides The RevoGrid MCP server is read-only and focused on retrieval quality. It currently exposes: - structured documentation search - example search across frameworks - feature matrix resolution for Core vs Pro support - migration notes between versions - typed API context derived from RevoGrid source Agents can use this to retrieve: - docs and guides - live examples and demo sources - feature availability - migration records - version metadata - TypeScript-driven API symbols and configuration hints ## Why this works well with RevoGrid RevoGrid already has strong typing and a source-driven API surface. That makes MCP especially effective here: the agent can ground its answers in real interfaces, events, and examples instead of relying on fuzzy pattern matching. When you use RevoGrid with AI tools, the best results usually come from this order: 1. ask the agent to inspect RevoGrid MCP results first 2. ask it to use RevoGrid types as the source of truth 3. ask it to adapt the result to your framework and version ## Install in AI coding tools Use the hosted RevoGrid MCP endpoint: ```text https://mcp.rv-grid.com ``` ### Claude Code ```bash claude mcp add --transport http revogrid https://mcp.rv-grid.com ``` ### Codex ```bash codex mcp add revogrid --url https://mcp.rv-grid.com ``` ### Cursor Open MCP settings and add this entry to `.cursor/mcp.json`: ```json { "mcpServers": { "RevoGrid": { "url": "https://mcp.rv-grid.com", "type": "http" } } } ``` ### VS Code Open `MCP: Add Server...` and choose a remote HTTP MCP server, or add this to `.vscode/mcp.json`: ```json { "servers": { "RevoGrid MCP": { "url": "https://mcp.rv-grid.com", "type": "http" } }, "inputs": [] } ``` ## Prompt patterns that work well These are good starting prompts for Codex, Cursor, Claude Code, VS Code MCP clients, or similar tools. ### Start from examples - `Create an editable React RevoGrid using the best matching public examples and docs.` - `Find the best Vue example for a custom column type and implement it.` - `Show the Angular getting-started resources for RevoGrid and use the latest matching setup.` ### Ground work in types - `Before writing code, look up the RevoGrid MCP docs and types for ColumnRegular, editors, and BeforeEdit.` - `Use RevoGrid types as the source of truth for props, events, and plugin configuration.` ### Check features before implementing - `Does RevoGrid support beforeedit in this version? Show docs, examples, and relevant types.` - `Does pivot exist, and is it Core or Pro? If Pro is unavailable, recommend the closest public fallback.` ### Migrate safely - `I am upgrading RevoGrid from 3.x to 4.x. Find migration notes, renamed symbols, and changed defaults that affect editing and events.` ## Recommended workflow for agents If you are using an AI coding assistant on a RevoGrid codebase, ask it to: 1. search RevoGrid MCP before writing code 2. prefer public examples over free-form code generation 3. confirm Core vs Pro availability before suggesting a feature 4. check RevoGrid types when property names or event payloads matter 5. link back to the relevant docs or examples in the answer This workflow tends to produce smaller, more accurate patches with fewer invented APIs. ## What to ask for explicitly To get the highest-quality output from an agent, be specific about: - framework: React, Vue, Angular, Svelte, or vanilla - version: if you are pinned to a RevoGrid release line - licensing: whether the solution must stay public/Core-only - behavior: editing, pinning, grouping, virtualization, filtering, export, or plugins For example: ```text Create a Core-only React RevoGrid with editable cells and custom column types. Use RevoGrid MCP results first, prefer runnable examples, and validate the final config against RevoGrid types. ``` ## Related pages - [Quick Start](https://rv-grid.com/guide/) - [Overview](https://rv-grid.com/guide/overview) - [Examples](https://rv-grid.com/demo/) - [Migration](https://rv-grid.com/guide/migration) - [Typings](https://rv-grid.com/guide/types/README) --- # RevoGrid Advanced Configuration Source: https://rv-grid.com/guide/advanced-configuration Description: Configure advanced RevoGrid props such as columnTypes, rowDefinitions, trimmedRows, additionalData, registerVNode, getProviders, and custom plugin hooks. This guide covers public props and methods that are powerful, but usually only needed once your grid becomes part of a larger application architecture. ## `columnTypes` `columnTypes` lets you define reusable column presets and reference them by name: ```ts grid.columnTypes = { readonlyText: { readonly: true, size: 180, }, }; grid.columns = [ { prop: 'name', name: 'Name', columnType: 'readonlyText' }, ]; ``` Use this when many columns share the same editor, renderer, read-only rule, or sizing rules. More realistic example: ```ts grid.columnTypes = { money: { size: 140, readonly: false, cellProperties: () => ({ class: { 'money-cell': true, }, }), }, lockedMeta: { readonly: true, size: 180, }, }; grid.columns = [ { prop: 'id', name: 'ID', columnType: 'lockedMeta' }, { prop: 'total', name: 'Total', columnType: 'money' }, ]; ``` ## `rowDefinitions` `rowDefinitions` applies row-level configuration such as custom row size. ```ts grid.rowDefinitions = [ { type: 'rgRow', index: 0, size: 48 }, ]; ``` This is the right tool for row-specific layout changes instead of trying to force layout through cell templates alone. Example with multiple row regions: ```ts grid.rowDefinitions = [ { type: 'rowPinStart', index: 0, size: 56 }, { type: 'rgRow', index: 10, size: 44 }, ]; ``` ## `trimmedRows` and `addTrimmed` `trimmedRows` hides source rows from the main viewport by physical index: ```ts grid.trimmedRows = { 2: true, 4: true, }; ``` For dynamic workflows, use: ```ts await grid.addTrimmed({ 10: true, 11: true }, 'external'); ``` Filtering uses trimming internally, but trimming is also useful for external rule-based visibility. Typical use cases: - hide archived rows without removing them from the source - keep a temporary working subset visible - combine application rules with filter-driven row visibility ## `additionalData` `additionalData` passes contextual data into renderers, editors, and plugins. ```ts grid.additionalData = { currentUserRole: 'manager', currency: 'EUR', }; ``` Use it for integration context, helper services, or framework-level references. Avoid turning it into a second source of truth for row data. In renderers or editors, `additionalData` is often used for: - current locale or currency - permission flags - external services - framework context passed into custom templates ## `registerVNode` `registerVNode` is for advanced cases where you want to register extra virtual nodes inside the grid, often from plugins. ```ts grid.registerVNode = [ config => h('div', { class: 'my-extra-panel' }, 'Extra UI'), ]; ``` This is not needed for normal application usage, but it is important for plugin-style extensions. If the extra UI depends on application state, call `refreshExtraElements()` after updating the state so the registered VNodes can re-render. ## `getProviders()` ```ts const providers = await grid.getProviders(); ``` Providers expose access to grid services such as: - data - dimension - selection - column - viewport - plugin service This is one of the key integration surfaces for plugin-oriented work. Example: ```ts const providers = await grid.getProviders(); const visibleMainRows = providers?.data.stores.rgRow.store.get('items'); console.log(visibleMainRows); ``` ## `getPlugins()` ```ts const plugins = await grid.getPlugins(); ``` Use this when you need to inspect or coordinate active plugin instances from application code. Example: ```ts const plugins = await grid.getPlugins(); plugins.forEach(plugin => { console.log(plugin.constructor.name); }); ``` ## Other advanced props worth knowing ### `canFocus` Disable focus rendering when the grid is used as a read-only viewer: ```ts grid.canFocus = false; ``` ### `useClipboard` Disable built-in clipboard behavior when your app needs to fully own copy/paste: ```ts grid.useClipboard = false; ``` ### `stretch` Control how columns fill remaining width: ```ts grid.stretch = 'last'; ``` ### `accessible` Keep accessibility enabled unless you have a very specific reason to disable it: ```ts grid.accessible = true; ``` ## Related guides - [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control) - [Grid Performance and Virtualization](https://rv-grid.com/guide/performance) - [Plugin Guide](https://rv-grid.com/guide/plugin/) - [API: RevoGrid](https://rv-grid.com/guide/api/revoGrid) --- # RevoGrid Event Patterns and Lifecycles Source: https://rv-grid.com/guide/events-guide Description: Source-backed event lifecycle diagrams for RevoGrid, including root grid events, internal component chains, and plugin-driven flows such as editing, clipboard, sorting, filtering, focus, scrolling, and row ordering. This page maps the event graph from the current source, not from assumptions. Source priority used for this guide: - [`src/components/revoGrid/revo-grid.tsx`](https://rv-grid.com/Users/maks/Projects/revogrid-pro-advance/revogrid/src/components/revoGrid/revo-grid.tsx) - [`src/components/overlay/revogr-overlay-selection.tsx`](https://rv-grid.com/Users/maks/Projects/revogrid-pro-advance/revogrid/src/components/overlay/revogr-overlay-selection.tsx) - [`src/components/clipboard/revogr-clipboard.tsx`](https://rv-grid.com/Users/maks/Projects/revogrid-pro-advance/revogrid/src/components/clipboard/revogr-clipboard.tsx) - [`src/plugins/sorting/sorting.plugin.ts`](https://rv-grid.com/Users/maks/Projects/revogrid-pro-advance/revogrid/src/plugins/sorting/sorting.plugin.ts) - [`src/plugins/filter/filter.plugin.tsx`](https://rv-grid.com/Users/maks/Projects/revogrid-pro-advance/revogrid/src/plugins/filter/filter.plugin.tsx) - [`src/components/header/revogr-header.tsx`](https://rv-grid.com/Users/maks/Projects/revogrid-pro-advance/revogrid/src/components/header/revogr-header.tsx) - [`src/components/selectionFocus/revogr-focus.tsx`](https://rv-grid.com/Users/maks/Projects/revogrid-pro-advance/revogrid/src/components/selectionFocus/revogr-focus.tsx) - [`src/components/editors/revogr-edit.tsx`](https://rv-grid.com/Users/maks/Projects/revogrid-pro-advance/revogrid/src/components/editors/revogr-edit.tsx) - [`src/components/order/revogr-order-editor.tsx`](https://rv-grid.com/Users/maks/Projects/revogrid-pro-advance/revogrid/src/components/order/revogr-order-editor.tsx) - [`src/components/data/revogr-data.tsx`](https://rv-grid.com/Users/maks/Projects/revogrid-pro-advance/revogrid/src/components/data/revogr-data.tsx) - [`src/components/scroll/revogr-viewport-scroll.tsx`](https://rv-grid.com/Users/maks/Projects/revogrid-pro-advance/revogrid/src/components/scroll/revogr-viewport-scroll.tsx) - [`src/types/events.ts`](https://rv-grid.com/Users/maks/Projects/revogrid-pro-advance/revogrid/src/types/events.ts) ## How to read these diagrams - `revo-grid` events are the public root lifecycle most app code listens to. - Child-component events are often the trigger layer that `revo-grid` listens to and translates. - Some plugin events are real but not part of the typed root `RevogridEvents` union. - If a `before*` event is cancelable, the branch stops at that point. ## Event Layers ```mermaid flowchart TB A[User action or prop change] --> B[Child component event] B --> C[revo-grid listener or watcher] C --> D[Plugin reaction] D --> E[Data or viewport mutation] E --> F[After-event or render event] ``` ## Root Grid Lifecycle This is the outer lifecycle created by `componentWillLoad`, watchers, and render hooks. ```mermaid flowchart TD A[connectedCallback] --> B[created] B --> C[componentWillLoad] C --> D[themeChanged] C --> E[columnChanged] C --> F[dataSourceChanged source] C --> G[dataSourceChanged pinnedTopSource] C --> H[dataSourceChanged pinnedBottomSource] C --> I[rowDefChanged] C --> J[aftergridinit] J --> K[componentWillRender] K --> L[beforegridrender] L --> M[render] M --> N[componentDidRender] N --> O[aftergridrender] E --> E1[beforecolumnsset] E1 --> E2[beforecolumnapplied] E2 --> E3[aftercolumnsset] F --> F1[beforesourceset] F1 --> F2[beforeanysource] F2 --> F3[aftersourceset] F3 --> F4[afteranysource] G --> G1[beforeanysource] G1 --> G2[afteranysource] H --> H1[beforeanysource] H1 --> H2[afteranysource] I --> I1[beforerowdefinition] ``` ## Focus, Selection, and Edit Lifecycle This flow starts in [`revogr-overlay-selection.tsx`](https://rv-grid.com/Users/maks/Projects/revogrid-pro-advance/revogrid/src/components/overlay/revogr-overlay-selection.tsx) and is completed by `revo-grid` plus [`revogr-focus.tsx`](https://rv-grid.com/Users/maks/Projects/revogrid-pro-advance/revogrid/src/components/selectionFocus/revogr-focus.tsx). ```mermaid flowchart TD A[Mouse down or keyboard navigation] --> B[beforecellfocusinit] B --> C[revo-grid listens] C --> D[beforecellfocus] D --> E[applyfocus] E --> F[focuscell] F --> G[revogr-focus render] G --> H[beforefocusrender] H --> I[beforescrollintoview] I --> J[afterfocus] J --> K[revo-grid afterfocus duplicate] F --> L[Double click or keypress starts edit] L --> M[setedit] M --> N[revo-grid onSetedit] N --> O[beforeeditstart] O --> P[selection store edit state] P --> Q[beforeeditrender] Q --> R[revogr-edit mounted] R --> S[celleditinit or closeedit] S --> T[celledit] T --> U[beforecellsave] U --> V[celleditapply] V --> W[revo-grid beforeedit] W --> X[dataProvider.setCellData] X --> Y[afteredit] S --> Z[closeedit] Z --> AA[canceledit] ``` ### Edit commit notes - `beforeeditstart` blocks opening the editor. - `beforecellsave` blocks the overlay from forwarding the save. - `beforeedit` blocks the root data write. - `afteredit` fires after single-cell and range writes. ## Range, Autofill, and Clipboard Lifecycle The range flow is handled in the overlay and clipboard components, then translated into root edit events by `revo-grid`. ```mermaid flowchart TD A[Shift+focus drag or autofill drag] --> B[beforeapplyrange] B --> C[beforesetrange] C --> D[setrange] D --> E[Range visible in overlay] E --> F[Autofill handle or range apply] F --> G[selectionchangeinit] G --> H[revo-grid beforerange] H --> I[revo-grid beforeautofill] I --> J[beforerangedataapply] J --> K[beforesettemprange] K --> L[settemprange] L --> M[beforerangecopyapply] M --> N[rangeeditapply] N --> O[revo-grid beforerangeedit] O --> P[dataProvider.setRangeData] P --> Q[afteredit] ``` ### Clipboard copy/cut ```mermaid flowchart TD A[Document copy] --> B[beforecopy] B --> C[copyregion] C --> D[overlay beforecopyregion] D --> E[clipboardrangecopy] E --> F[beforecopyapply] F --> G[clipboard text written] H[Document cut] --> I[beforecut] I --> J[copy path runs] J --> K[clearregion] K --> L[overlay clearCell or range clear] L --> M[celleditapply or rangeeditapply] M --> N[beforeedit or beforerangeedit] N --> O[afteredit] ``` ### Clipboard paste ```mermaid flowchart TD A[Document paste] --> B[beforepaste] B --> C[beforepasteapply] C --> D[pasteregion] D --> E[overlay clipboardrangepaste] E --> F[autofill service onRangeApply] F --> G[selectionchangeinit] G --> H[beforerange] H --> I[beforeautofill] I --> J[rangeeditapply] J --> K[beforerangeedit] K --> L[afteredit] D --> M[afterpasteapply] ``` ## Header, Sorting, and Filtering Lifecycle Header events start in [`revogr-header.tsx`](https://rv-grid.com/Users/maks/Projects/revogrid-pro-advance/revogrid/src/components/header/revogr-header.tsx). Sorting and filtering then hook into those events. ```mermaid flowchart TD A[Header render] --> B[beforeheaderrender] B --> C[beforegroupheaderrender] C --> D[afterheaderrender] E[Header click] --> F[beforeheaderclick] F --> G[revo-grid headerclick] G --> H[SortingPlugin or FilterPlugin] I[Header resize gesture] --> J[beforeheaderresize] J --> K[headerresize] K --> L[viewport resize service] L --> M[aftercolumnresize] ``` ### Sorting ```mermaid flowchart TD A[beforeheaderclick on sortable column] --> B[SortingPlugin headerclick] B --> C[beforesorting] C --> D[beforesortingapply] D --> E[sorting state updated in plugin] E --> F[startSorting] F --> G[sort data stores] G --> H[aftersortingapply] G --> I[source watchers may later re-trigger beforeanysource] J[beforeanysource] --> K[SortingPlugin beforesourcesortingapply] K --> L[startSorting] L --> G M[sorting prop change or updateColumnSorting] --> N[sortingconfigchanged] N --> O[SortingPlugin config update] O --> F ``` ### Filtering ```mermaid flowchart TD A[headerclick on filter button] --> B[FilterPlugin opens panel] B --> C[filterChange or resetChange] C --> D[runFiltering] D --> E[beforefilterapply] E --> F[getRowFilter] F --> G[beforefiltertrimmed] G --> H[dataProvider.setTrimmed filter] H --> I[afterfilterapply] H --> J[revo-grid beforetrimmed if trimmedRows API used] H --> K[Grid render with filtered rows] L[filter prop change] --> M[filterconfigchanged] M --> D N[aftersourceset] --> O[FilterPlugin reruns active filters] O --> D ``` ## Row Ordering Lifecycle ```mermaid flowchart TD A[dragstartcell] --> B[revogr-order-editor dragStart] B --> C[rowdragstartinit] C --> D[revo-grid rowdragstart] D --> E[orderService.start] E --> F[rowdragmoveinit] F --> G[rowdragmousemove] G --> H[rowdropinit] H --> I[revo-grid roworderchanged] I --> J[roworderchange] J --> K[dataProvider.changeOrder] K --> L[rowdragendinit] ``` ## Scroll and Data Render Lifecycle ```mermaid flowchart TD A[Viewport resize] --> B[resizeviewport] B --> C[dimension provider updates] C --> D[contentsizechanged] E[Viewport scroll] --> F[scrollviewport] F --> G[GridScrollingService] G --> H[viewportscroll] F --> I[scrollchange] F --> J[scrollviewportsilent] K[Data component will render] --> L[beforedatarender] L --> M[beforerowrender] M --> N[beforecellrender] N --> O[afterrender] ``` ## Source and Config Watchers These are not user gestures. They are reactive lifecycle edges triggered by prop updates. ```mermaid flowchart TD A[source change] --> B[beforesourceset] B --> C[beforeanysource] C --> D[aftersourceset] D --> E[afteranysource] F[columns change] --> G[beforecolumnsset] G --> H[beforecolumnapplied] H --> I[aftercolumnsset] J[theme change] --> K[afterthemechanged] L[rowDefinitions change] --> M[beforerowdefinition] N[trimmedRows change] --> O[beforetrimmed] O --> P[aftertrimmed] Q[sorting change] --> R[sortingconfigchanged] S[filter change] --> T[filterconfigchanged] U[rowHeaders change] --> V[rowheaderschanged] W[additionalData change] --> X[additionaldatachanged] ``` ## Public vs Internal Event Surface Use [`src/types/events.ts`](https://rv-grid.com/Users/maks/Projects/revogrid-pro-advance/revogrid/src/types/events.ts) as the typed public event catalog. Most application integrations should anchor on: - `created`, `aftergridinit`, `beforegridrender`, `aftergridrender` - `beforesourceset`, `beforeanysource`, `aftersourceset`, `afteranysource` - `beforecolumnsset`, `beforecolumnapplied`, `aftercolumnsset` - `beforeeditstart`, `beforeedit`, `beforerangeedit`, `afteredit` - `beforecellfocus`, `beforefocuslost`, `afterfocus` - `beforerange`, `beforeautofill` - `beforesorting`, `beforesortingapply`, `beforesourcesortingapply`, `sortingconfigchanged` - `beforefilterapply`, `beforefiltertrimmed`, `beforetrimmed`, `aftertrimmed` - `rowdragstart`, `roworderchanged` - `viewportscroll`, `contentsizechanged`, `aftercolumnresize` Useful internal or plugin-only events that also appear in flows: - `beforeapplyrange`, `beforesetrange`, `setrange` - `beforepaste`, `beforepasteapply`, `pasteregion`, `afterpasteapply` - `beforecopyregion`, `clipboardrangecopy`, `clipboardrangepaste` - `beforefocusrender`, `beforescrollintoview` - `beforeheaderclick`, `beforeheaderrender`, `beforegroupheaderrender` - `aftersortingapply`, `afterfilterapply`, `newRows`, `rtlstatechanged` ## Recommended Hooks by Use Case ### Validate edits before commit - `beforeedit` - `beforerangeedit` - `beforecellsave` if you need to stop the overlay before the root write ### Persist changes after commit - `afteredit` - `aftersourceset` if you replace source externally ### Drive custom navigation - `beforecellfocus` - `beforefocuslost` - `beforenextvpfocus` - `afterfocus` ### Observe filter and sorting transitions - `beforefilterapply` - `beforefiltertrimmed` - `beforesorting` - `beforesortingapply` - `beforesourcesortingapply` - `sortingconfigchanged` ### Track render and viewport changes - `beforegridrender` - `aftergridrender` - `beforedatarender` - `afterrender` - `viewportscroll` - `contentsizechanged` ## Related guides - [Editing](https://rv-grid.com/guide/editing) - [Filtering](https://rv-grid.com/guide/filters) - [Sorting](https://rv-grid.com/guide/sorting) - [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control) - [API: Events](https://rv-grid.com/guide/api/events) --- # TSX Template Source: https://rv-grid.com/guide/jsx.template # JSX/TSX - Custom Content Rendering JSX (or TSX if you're using TypeScript) is a syntax extension to JavaScript that simplifies template rendering. We highly recommend using JSX/TSX as it will make your development process much easier. ```jsx const MyTemplate = (h, column) =>
{ column.name }
``` While JSX is commonly associated with React, it is not exclusive to it. JSX is simply a way to render content and can be used in any project you choose. We use JSX/TSX in all our projects because it simplifies the rendering process. For example, consider a regular column header rendered with `createElement`: ```js const columnTemplate = (createElement, column) => { return createElement('span', { style: { color: 'red' }, }, createElement('div', { class: 'me' }, column.name)); }; const columns = [{ name: 'Person name', prop: 'name', columnTemplate }]; ``` Now imagine having 10 or more child nodes. This can quickly become complex. Let's simplify it with JSX or TSX. > [!WARNING] > Remember to escape any HTML code to prevent XSS attacks. First, create a myJsx.jsx file: ```jsx export const myTemplate = (h, column) => { return
{column.name}
; } ``` Then in our main file: ```js import { myTemplate } from `./myJsx`; const columns = [{ name: 'Person name', prop: 'name', columnTemplate: myTemplate }]; ``` Quite simple, right? ## Using Keys in JSX Templates > [!IMPORTANT] > **Keys are essential for VNode reconciliation.** When rendering lists or dynamic content, always provide unique keys to help the virtual DOM accurately identify, track, and update nodes. Use keys thoughtfully, as incorrect usage can lead to inefficient updates or unexpected behavior. Keys allow the virtual DOM to: - **Identify unique nodes** - Distinguish between different items even when content is similar - **Optimize updates** - Efficiently update only the nodes that have changed - **Preserve state** - Maintain component state when items are reordered or filtered ### Basic Key Usage When rendering multiple elements, always provide a unique `key` prop: ```jsx const MyTemplate = (h, props) => { const items = props.model.items || []; return (
{items.map((item, index) => (
{item.name}
))}
); } ``` ### Best Practices for Keys 1. **Use stable, unique identifiers** - Prefer IDs from your data over array indices: ```jsx // ✅ Good - uses stable ID {items.map(item => (
{item.name}
))} // ⚠️ Acceptable - uses index when no ID available {items.map((item, index) => (
{item.name}
))} ``` 2. **Combine identifiers for uniqueness** - When rendering cells, combine row and column identifiers: ```jsx const CellTemplate = (h, props) => { return (
{props.model[props.prop]}
); } ``` 3. **Avoid changing keys** - Keys should remain stable for the same item across renders: ```jsx // ❌ Bad - key changes on every render
Content
// ✅ Good - key is stable
Content
``` ### Example: Cell Template with Keys ```jsx const CellWithMultipleItems = (h, props) => { const tags = props.model.tags || []; return (
{props.model.name}
{tags.map(tag => ( {tag.label} ))}
); } ``` ## TypeScript JSX Cell Template Demo [Check out this sample.](https://codesandbox.io/s/revo-grid-vanilla-jsx-zj0q6?file=/src/index.js) We use babel-jsx with minimal configuration settings. --- # RevoGrid Features and Definitions Source: https://rv-grid.com/guide/defs Description: A practical glossary for RevoGrid concepts, including cells, columns, rows, ranges, viewports, plugins, props, methods, and virtual scrolling. This page is a quick glossary for the concepts used throughout the RevoGrid docs. It is especially useful when you are moving between high-level guides, framework wrappers, and the API reference. ## Lifecycle Hooks For detailed interactions and operations, RevoGrid provides a variety of [events](https://rv-grid.com/guide/api/revoGrid#Events) that function similarly to lifecycle hooks, allowing developers to listen and respond to different stages and actions within the grid's lifecycle. Here's a brief overview of some key events which can help in managing grid behavior, data manipulation, and user interactions: ### Source - **`beforeanysource`**: Triggered before data application in [`data source`](https://rv-grid.com/guide/defs#Data-Source). - **`afteranysource`**: Fires after all rows are updated. - **`beforesourceset`**: Fired before [`data source`](https://rv-grid.com/guide/defs#Data-Source) application. - **`aftersourceset`**: Occurs after rows are updated. - **`beforetrimmed`**: Triggered before [`trimmed rows`](https://rv-grid.com/guide/defs#Trimmed-Rows) are applied. - **`aftertrimmed`**: Notifies when [`trimmed rows`](https://rv-grid.com/guide/defs#Trimmed-Rows) is applied. ### Column - **`beforecolumnapplied`**: Happens before columns are applied. - **`beforecolumnsset`**: Triggered before column updates. - **`aftercolumnsset`**: Fired when columns are updated. ### Edit - **`beforeedit`**: Triggered before an edit is applied. - **`beforerangeedit`**: Occurs before a range edit is applied. - **`beforeautofill`**: Fired before autofill operation. - **`afteredit`**: Executes after an edit action is completed. ### Focus/Selection - **`beforecellfocus`**: Occurs before cell focus changes. - **`beforefocuslost`**: Happens before grid focus is lost. - **`afterfocus`**: Fires after focus render is completed. Events provide a structured approach to handling RevoGrid's functionalities, making it easier to implement and manage complex data grid behaviors in web applications. ## API The public API is the combination of: - props such as `columns`, `source`, `filter`, `grouping`, and `additionalData` - methods such as `setDataAt`, `scrollToRow`, `setCellsFocus`, and `getVisibleSource` - events such as `beforeedit`, `afteredit`, `beforefilterapply`, and `beforesourceset` Start at [RevoGrid API](https://rv-grid.com/guide/api/revoGrid). ## Cell The intersection point of a row and a column in the grid, capable of displaying and editing data. A cell can have custom renderers and editors, which are tightly coupled with the column properties. You can [customize cells using templates](https://rv-grid.com/guide/cell/renderer) to change their appearance or behavior. ### Cell editor A cell editor is the UI used to modify a value. RevoGrid ships with a core editor flow and supports custom editor registration through the `editors` prop. ### Cell template A cell template is a custom renderer for displaying richer cell content while keeping the grid virtualized. ### Cell merge Cell merging refers to combining adjacent cells into a larger visual area. This is available in RevoGrid Pro. ## Clipboard Clipboard support enables copy, cut, and paste workflows. It is controlled by `useClipboard` and range selection behavior. See [Clipboard Operations](https://rv-grid.com/guide/clipboard). ## Column Columns define how the grid reads and displays row data. A column can configure: - `prop` mapping - `name` - `size`, `minSize`, `maxSize` - `sortable` - `filter` - `editor` - `cellTemplate` - `cellProperties` - `readonly` - `pin` - `columnType` Related guides: - [Column Definitions](https://rv-grid.com/guide/column/) - [Custom Columns](https://rv-grid.com/guide/column/types) - [Column Groups](https://rv-grid.com/guide/column/grouping) ## Data source The data source is the row array shown by the grid. The main dataset is assigned through `source`, while pinned row regions use `pinnedTopSource` and `pinnedBottomSource`. ## Data model The data model is the shape of each row object inside your source array. ```typescript interface Person { id: number; name: string; age: number; email: string; } ``` ## Event Events are how RevoGrid exposes lifecycle and interaction hooks. Many events are cancelable and let you change the behavior before the grid commits it. Examples: - editing: `beforeedit`, `afteredit` - data updates: `beforesourceset`, `aftersourceset` - filtering: `beforefilterapply`, `beforefiltertrimmed` - focus: `beforecellfocus`, `beforefocuslost`, `afterfocus` See [Event Patterns and Lifecycles](https://rv-grid.com/guide/events-guide) and [Hooks and Events API](https://rv-grid.com/guide/api/events). ## Export The core export plugin supports CSV file export workflows from the grid surface. See [Export Data](https://rv-grid.com/guide/export.plugin). Excel-focused export workflows are available in Pro, and browser-side PDF export is available through the [`@revolist/revogrid-pdf-export`](https://rv-grid.com/guide/pdf-export) add-on plugin. ## Focus Focus is the active cell target used for keyboard navigation, editing, and selection overlays. It can be enabled or disabled with `canFocus`. Useful methods: - `setCellsFocus` - `clearFocus` - `getFocused` ## Range A range is a rectangular selection of cells. Range selection is enabled with the `range` prop and exposed through `getSelectedRange`. ### Range autofill Autofill extends a selected value or pattern across a dragged range. Advanced autofill workflows are available in RevoGrid Pro. ## Keyboard support RevoGrid includes keyboard navigation for moving focus, editing cells, selecting ranges, and copying or pasting data. Custom features should integrate with keyboard behavior rather than bypassing it. ## Method Methods are imperative APIs exposed on the grid instance. They are useful when application state or external controls need to drive the grid directly. Examples: - `scrollToRow` - `scrollToColumnProp` - `setCellEdit` - `setDataAt` - `getVisibleSource` ## Plugin Plugins extend grid behavior without changing the core component. RevoGrid includes built-in plugins for filtering, sorting, exporting, grouping, stretching, accessibility, and more. The `plugins` prop can also receive custom plugin classes. For plugin-oriented props and provider access, see [Advanced Configuration](https://rv-grid.com/guide/advanced-configuration). ### Filtering The filtering plugin hides rows that do not match the selected criteria. ### Sorting The sorting plugin updates column order state and applies sorted row order to the source. ### Pagination Pagination is not part of the OSS core guide surface today. It is available through RevoGrid Pro workflows. ## Performance Performance in RevoGrid comes from virtual rendering, viewport separation, lightweight renderers, and explicit data update methods. Read [Grid Performance and Virtualization](https://rv-grid.com/guide/performance). ## Prop A prop is a public configuration field passed to the grid, such as `columns`, `source`, `filter`, `readonly`, `stretch`, or `grouping`. ## Row Rows represent records in the source dataset and can be customized through pinned regions, row headers, row definitions, grouping, and trimming. ### Row grouping Row grouping groups records under shared labels based on selected props. See [Row Grouping](https://rv-grid.com/guide/row/grouping). ### Row headers Row headers add an index or custom left-hand row area. See [Row Headers](https://rv-grid.com/guide/row/headers). ### Row pinning Pinned rows stay visible in `pinnedTopSource` or `pinnedBottomSource` while the main dataset scrolls. ### Trimmed rows Trimmed rows are source rows that exist but are currently hidden from the visible viewport. Filtering uses trimming internally, and you can also control trimming directly with `trimmedRows` or `addTrimmed`. ## Viewport A viewport is one rendered region of the grid. RevoGrid uses separate viewports for: - main rows: `rgRow` - pinned top rows: `rowPinStart` - pinned bottom rows: `rowPinEnd` - main columns: `rgCol` - pinned start columns: `colPinStart` - pinned end columns: `colPinEnd` Events often expose indexes relative to a viewport, not the original array position. See [Understanding Viewports](https://rv-grid.com/guide/viewports). ### Virtual scrolling Virtual scrolling means the grid renders only what is visible, plus a small rendering frame. This keeps large grids usable and responsive. ## VNode Reactive DOM At the core of RevoGrid's high performance is its use of a reactive DOM model (similar one you would find in any popular reactive framework [Vue Virtual DOM](https://vuejs.org/guide/extras/rendering-mechanism), [React Virtual DOM](https://legacy.reactjs.org/docs/faq-internals.html), etc.). This model ensures that only the parts of the grid that need updating are re-rendered, rather than the entire grid. This selective rendering mechanism is crucial for handling large amounts of data, as it significantly reduces the amount of DOM manipulation required, leading to smoother scrolling and interactions. ## Web Component RevoGrid is implemented as a Web Component, which is why it can be used directly in JavaScript and wrapped by multiple frameworks without changing the core implementation. ## Related guides - [Overview](https://rv-grid.com/guide/overview) - [Grid Performance and Virtualization](https://rv-grid.com/guide/performance) - [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control) - [Advanced Configuration](https://rv-grid.com/guide/advanced-configuration) --- # API Source: https://rv-grid.com/guide/api/revoGrid ## Overview Revogrid - High-performance, customizable grid library for managing large datasets. ### Events guide For a comprehensive events guide, check the [Events API Page](https://rv-grid.com/guide/api/events). All events propagate to the root level of the grid. [Dependency tree](#Dependencies). ### Type definitions Read [type definition file](https://github.com/revolist/revogrid/blob/master/src/interfaces.d.ts) for the full interface information. All complex property types such as `ColumnRegular`, `ColumnProp`, `ColumnDataSchemaModel` can be found there. ### HTMLRevoGridElement ## Properties | Property | Attribute | Description | Type | Default | | ---------------------------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | | `accessible` | `accessible` | Enable accessibility. If disabled, the grid will not be accessible. | `boolean` | `true` | | `additionalData` | -- | Additional data to be passed to plugins, renders or editors. For example if you need to pass Vue component instance. | `AdditionalData` | `{}` | | `applyOnClose` | `apply-on-close` | Apply changes in editor when closed except 'Escape' cases. If custom editor in use method getValue required. Check interfaces.d.ts `EditorBase` for more info. | `boolean` | `false` | | `autoSizeColumn` | `auto-size-column` | Autosize config. Enables columns autoSize. For more details check `autoSizeColumn` plugin. By default disabled, hence operation is not performance efficient. `true` to enable with default params (double header separator click for autosize). Or define config. See `AutoSizeColumnConfig` for more details. | `boolean \| { mode?: ColumnAutoSizeMode \| undefined; allColumns?: boolean \| undefined; letterBlockSize?: number \| undefined; preciseSize?: boolean \| undefined; }` | `false` | | `canDrag` | `can-drag` | Disable native drag&drop plugin. | `boolean` | `true` | | `canFocus` | `can-focus` | When true cell focus appear. | `boolean` | `true` | | `canMoveColumns` | `can-move-columns` | Enable column move plugin. | `boolean` | `true` | | `colSize` | `col-size` | Indicates default column size. | `number` | `100` | | `columnTypes` | -- | Column Types Format. Every type represent multiple column properties. Types will be merged but can be replaced with column properties. Types were made as separate objects to be reusable per multiple columns. | `{ [name: string]: ColumnType>; }` | `{}` | | `columns` | -- | Columns - defines an array of grid columns. Can be column or grouped column. | `(ColumnRegular> \| ColumnGrouping)[]` | `[]` | | `disableVirtualX` | `disable-virtual-x` | Disable lazy rendering mode for the `X axis`. Use when not many columns present and you don't need rerenader cells during scroll. Can be used for initial rendering performance improvement. | `boolean` | `false` | | `disableVirtualY` | `disable-virtual-y` | Disable lazy rendering mode for the `Y axis`. Use when not many rows present and you don't need rerenader cells during scroll. Can be used for initial rendering performance improvement. | `boolean` | `false` | | `editors` | -- | Custom editors register. | `{ [name: string]: EditorCtr; }` | `{}` | | `exporting` | `exporting` | Enable export plugin. | `boolean` | `true` | | `filter` | `filter` | Enables filter plugin. Enabled by default; set to `false` to opt out. Can be boolean. Or can be filter collection See `FilterCollection` for more info. | `ColumnFilterConfig \| boolean` | `true` | | `focusTemplate` | -- | Apply changes typed in editor on editor close except Escape cases. If custom editor in use method `getValue` required. Check `interfaces.d.ts` `EditorBase` for more info. | `(createElement: HyperFunc, detail: FocusRenderEvent) => any` | `undefined` | | `frameSize` | `frame-size` | Defines how many rows/columns should be rendered outside visible area. | `number` | `1` | | `grouping` | -- | Group rows based on this property. Define properties to be groped by grouping plugin See `GroupingOptions`. | `{ props?: ColumnProp[] \| undefined; preserveGroupingOnUpdate?: boolean \| undefined; groupLabelTemplate?: GroupLabelTemplateFunc \| undefined; groupCellTemplate?: GroupCellTemplateFunc \| undefined; } & ExpandedOptions` | `undefined` | | `hideAttribution` | `hide-attribution` | Please only hide the attribution if you are subscribed to Pro version | `boolean` | `false` | | `jobsBeforeRender` | -- | Prevent rendering until job is done. Can be used for initial rendering performance improvement. When several plugins require initial rendering this will prevent double initial rendering. | `Promise[]` | `[]` | | `noHorizontalScrollTransfer` | `no-horizontal-scroll-transfer` | Prevents horizontal scroll state from being mirrored across viewport sections. | `boolean` | `false` | | `pinnedBottomSource` | -- | Pinned bottom Source: {[T in ColumnProp]: any} - defines pinned bottom rows data source. | `DataType[]` | `[]` | | `pinnedTopSource` | -- | Pinned top Source: {[T in ColumnProp]: any} - defines pinned top rows data source. | `DataType[]` | `[]` | | `plugins` | -- | Custom grid plugins. Can be added or removed at runtime. Every plugin should be inherited from BasePlugin class. For more details check [Plugin guide](https://rv-grid.com/guide/plugin/) | `(typeof BasePlugin)[]` | `[]` | | `range` | `range` | When true, user can select a cell range. Required for range-based clipboard fill. | `boolean` | `false` | | `readonly` | `readonly` | When true, grid in read only mode. | `boolean` | `false` | | `registerVNode` | -- | Register new virtual node inside of grid. Used for additional items creation such as plugin elements. Should be set before grid render inside of plugins. Can return VNode result of h() function or a function that returns VNode. Function can be used for performance improvement and additional renders. | `(VNode \| ((c: ExtraNodeFuncConfig) => VNode))[]` | `[]` | | `resize` | `resize` | When true, columns are resizable. | `boolean` | `true` | | `resizeRow` | `resize-row` | Enables row resizing. Pass a configuration object to customize the height limits or enable resize edges across the full row. | `boolean \| { minHeight?: number \| undefined; maxHeight?: number \| undefined; fullRow?: boolean \| undefined; }` | `false` | | `rowClass` | `row-class` | Row class property mapping. Map custom classes to rows from row object data. Define this property in rgRow object and this will be mapped as rgRow class. | `string` | `''` | | `rowDefinitions` | -- | Custom row properies to be applied. See `RowDefinition` for more info. | `RowDefinition[]` | `[]` | | `rowHeaders` | `row-headers` | Excel like functionality. Show row numbers. Also can be used for custom row header render if object provided. | `RowHeaders \| boolean` | `undefined` | | `rowSize` | `row-size` | Indicates default rgRow size. By default 0, means theme package size will be applied Alternatively you can use `rowSize` to reset viewport | `number` | `0` | | `rtl` | `rtl` | Enable right-to-left (RTL) mode. When enabled, columns will be displayed from right to left. | `boolean` | `false` | | `sorting` | -- | Alternative way to set sorting. `{columns: [{prop: 'name', order: 'asc'}]}` Use SortingPlugin to get current sorting state | `undefined \| { columns?: { prop: ColumnProp; order: Order; cellCompare?: CellCompareFunc \| undefined; }[] \| undefined; additive?: boolean \| undefined; }` | `undefined` | | `source` | -- | Source - defines main data source. Can be an Object or 2 dimensional array([][]); Keys/indexes referenced from columns Prop. | `DataType[]` | `[]` | | `stretch` | `stretch` | Stretch strategy for columns by `StretchColumn` plugin. For example if there are more space on the right last column size would be increased. | `boolean \| string` | `false` | | `theme` | `theme` | Theme name. | `string` | `'default'` | | `themeDefinitions` | -- | Per-grid custom theme definitions. Assign as a JavaScript property; complex values cannot be serialized as HTML attributes. | `ThemeDefinition[]` | `[]` | | `trimmedRows` | -- | Trimmed rows. Functionality which allows to hide rows from main data set. `trimmedRows` are physical `rgRow` indexes to hide. | `boolean \| number` | `{}` | | `useClipboard` | `use-clipboard` | When true enable clipboard. Can be boolean or clipboard config. | `ClipboardConfig \| boolean` | `true` | | `virtualX` | -- | Column dimensions that use X axis virtual rendering. Defaults to regular columns only to preserve pinned column behavior. Set to `['rgCol', 'colPinStart', 'colPinEnd']` to virtualize all column areas. | `DimensionCols[]` | `['rgCol']` | ## Events | Event | Description | Type | | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `additionaldatachanged` | Emmited after the additional data is changed | `CustomEvent` | | `afteranysource` | Emitted after each source update, whether from the pinned or main viewport. Useful for tracking all changes originating from sources in both the pinned and main viewports. | `CustomEvent<{ type: DimensionRows; source: DataType[]; }>` | | `aftercolumnresize` | Emitted after column resizing. Useful for retrieving the resized columns. | `CustomEvent<{ [index: number]: ColumnRegular>; }>` | | `aftercolumnsset` | Column updated | `CustomEvent<{ columns: ColumnCollection; order: SortingOrder; }>` | | `afteredit` | After data applied or range changed. | `CustomEvent>> \| D \| K>` | | `afterfocus` | After focus render finished. Can be used to access a focus element through `event.target`. This is just a duplicate of `afterfocus` from `revogr-focus.tsx`. | `CustomEvent>>` | | `aftergridinit` | Emmited after the grid is initialized. Connected to the DOM. | `CustomEvent` | | `aftergridrender` | Emmited after the grid is rendered. | `CustomEvent` | | `aftersortingapply` | By `SortingPlugin`
Triggered after sorting has been applied and completed.
Provides final sorting state and sorting column metadata when available. | `CustomEvent<{ sorting?: SortingOrder \| undefined; sortingColumns?: SortingColumnMap \| undefined; sortingOrder?: SortingColumnOrder \| undefined; types: DimensionRows[]; }>` | | `aftersourceset` | After main source/rows updated | `CustomEvent<{ type: DimensionRows; source: DataType[]; }>` | | `afterthemechanged` | Emmited after the theme is changed | `CustomEvent` | | `aftertrimmed` | Emitted after trimmed values have been applied. Useful for notifying when trimming of values has taken place. | `CustomEvent` | | `beforeanysource` | Before data apply on any source type. Can be source from pinned and main viewport. You can override data source here | `CustomEvent<{ type: DimensionRows; source: DataType[]; }>` | | `beforeautofill` | Before autofill is applied. To prevent the default behavior of applying the edit data, you can call `e.preventDefault()`. | `CustomEvent<{ type: DimensionRows; colType: DimensionCols; newRange: RangeArea; oldRange: RangeArea; mapping: OldNewRangeMapping; newData: { [newRowIndex: number]: DataType; }; }>` | | `beforecellfocus` | Before the cell focus is changed. To prevent the default behavior of changing the cell focus, you can call `e.preventDefault()`. | `CustomEvent>>>` | | `beforecolumnapplied` | Emitted before a column update is applied, after the column set is gathered and the viewport is updated. Useful for performing actions or modifications before the final application of the column update. | `CustomEvent<{ columns: Record>[]>; columnByProp: Record>[]>; columnGrouping: ColumnGroupingCollection; maxLevel: number; sort: Record>>; }>` | | `beforecolumnsgather` | Emitted before user column definitions are gathered into the internal column collection. Listeners can replace `detail.columns` to rewrite the raw column set before RevoGrid normalizes it. | `CustomEvent<{ columns: (ColumnRegular> \| ColumnGrouping)[]; }>` | | `beforecolumnsset` | Emitted before a column update is applied. Listeners can use this event to perform any necessary actions or modifications before the column update is finalized. | `CustomEvent<{ columns: Record>[]>; columnByProp: Record>[]>; columnGrouping: ColumnGroupingCollection; maxLevel: number; sort: Record>>; }>` | | `beforeedit` | Before the data is edited. To prevent the default behavior of editing data and use your own implementation, call `e.preventDefault()`. To override the edit result with your own value, set the `e.val` property to your desired value. | `CustomEvent>>>` | | `beforeeditstart` | Emitted before editing starts. Use e.preventDefault() to prevent the default edit behavior. | `CustomEvent>>>` | | `beforeexport` | Before export Use e.preventDefault() to prevent export Replace data in Event in case you want to modify it in export | `CustomEvent<{ data: DataType[]; } & ColSource>` | | `beforefilterapply` | Emitted before applying a filter to the data source. Use e.preventDefault() to prevent cell focus change. Modify if you need to change filters. | `CustomEvent<{ collection: Record; }>` | | `beforefiltertrimmed` | Emitted before applying a filter to the data source. Use e.preventDefault() to prevent the default behavior of trimming values and applying the filter. Modify the `collection` property if you want to change the filters. Modify the `itemsToFilter` property if you want to filter the indexes for trimming. | `CustomEvent<{ collection: Record; itemsToFilter: Record; }>` | | `beforefocuslost` | Before the grid focus is lost. To prevent the default behavior of changing the cell focus, you can call `e.preventDefault()`. | `CustomEvent> \| undefined; }>` | | `beforegridrender` | Emmited before the grid is rendered. | `CustomEvent` | | `beforerange` | Before autofill is applied. Runs before beforeautofill event. Use e.preventDefault() to prevent range. | `CustomEvent<{ type: DimensionRows; colType: DimensionCols; newRange: RangeArea; oldRange: RangeArea; mapping: OldNewRangeMapping; newData: { [newRowIndex: number]: DataType; }; }>` | | `beforerangeedit` | Before applying range data, specifically when a range selection occurs. To customize the data and prevent the default edit data from being set, you can call `e.preventDefault()`. | `CustomEvent` | | `beforerowdefinition` | Emitted before the row definition is applied. Useful for modifying or preventing the default row definition behavior. | `CustomEvent<{ vals: any; oldVals: any; }>` | | `beforesorting` | By `SortingPlugin`
Triggered immediately after header click.
First in sorting event sequence. Ff this event stops no other event called.
Use `e.preventDefault()` to prevent sorting. | `CustomEvent<{ column: ColumnRegular>; order: "asc" \| "desc"; additive: boolean; }>` | | `beforesortingapply` | By `SortingPlugin`
After `beforesorting`
Triggered after column data updated with new sorting order.
Use `e.preventDefault()` to prevent sorting data change. | `CustomEvent<{ column: ColumnRegular>; order: "asc" \| "desc"; additive: boolean; }>` | | `beforesourceset` | Before main source/rows data apply. You can override data source here | `CustomEvent<{ type: DimensionRows; source: DataType[]; }>` | | `beforesourcesortingapply` | By `SortingPlugin`
Same as `beforesorting` but triggered after `beforeanysource` (when source is changed).
Use `e.preventDefault()` to prevent sorting data change. | `CustomEvent<{ type: DimensionRows; sorting?: SortingOrder \| undefined; }>` | | `beforetrimmed` | Emitted before trimming values. Use e.preventDefault() to prevent the default behavior of trimming values. Modify the `trimmed` property if you want to filter the indexes for trimming. | `CustomEvent<{ trimmed: Record; trimmedType: string; type: string; }>` | | `contentsizechanged` | New content size has been applied. The size excludes the header. Currently, the event responsible for applying the new content size does not provide the actual size. To retrieve the actual content size, you can utilize the `getContentSize` function after the event has been triggered. | `CustomEvent<"colPinEnd" \| "colPinStart" \| "rgCol" \| "rgRow" \| "rowPinEnd" \| "rowPinStart">` | | `created` | Emmited after grid created | `CustomEvent` | | `filterconfigchanged` | Emitted when the filter configuration is changed | `CustomEvent` | | `headerclick` | On header click. | `CustomEvent>>` | | `rowdragstart` | This event is triggered when the row order change is started. To prevent the default behavior of changing the row order, you can call `e.preventDefault()`. To change the item name at the start of the row order change, you can set `e.text` to the desired new name. | `CustomEvent` | | `rowheaderschanged` | Emmited when the row headers are changed. | `CustomEvent` | | `roworderchanged` | Before the order of `rgRow` is applied. To prevent the default behavior of changing the order of `rgRow`, you can call `e.preventDefault()`. | `CustomEvent<{ from: number; to: number; }>` | | `sortingconfigchanged` | Emitted when the sorting configuration is changed SortingPlugin subsribed to this event | `CustomEvent<{ columns?: { prop: ColumnProp; order: Order; cellCompare?: CellCompareFunc \| undefined; }[] \| undefined; additive?: boolean \| undefined; }>` | | `viewportscroll` | Emitted when the viewport is scrolled. Useful for tracking viewport scrolling events. | `CustomEvent` | ## Methods ### `addTrimmed(trimmed: Record, trimmedType?: string, type?: DimensionRows) => Promise; trimmedType: string; type: string; }>>` Add trimmed by type #### Parameters | Name | Type | Description | | ------------- | ---------------------------- | ----------- | | `trimmed` | `{ [x: number]: boolean; }` | | | `trimmedType` | `string` | | | `type` | `DimensionRowPin \| "rgRow"` | | #### Returns Type: `Promise; trimmedType: string; type: string; }>>` ### `clearFocus() => Promise` Clear current grid focus. Grid has no longer focus on it. #### Returns Type: `Promise` ### `clearSorting() => Promise` Clears column sorting #### Returns Type: `Promise` ### `getColumnStore(type?: DimensionCols) => Promise>>` Provides access to column internal store observer Can be used for plugin support #### Parameters | Name | Type | Description | | ------ | ---------------------------- | ---------------- | | `type` | `DimensionColPin \| "rgCol"` | - type of column | #### Returns Type: `Promise>, DimensionCols>>>` ### `getColumns() => Promise` Receive all columns in data source #### Returns Type: `Promise>[]>` ### `getContentSize() => Promise` Get size of content Including all pinned data #### Returns Type: `Promise` ### `getFocused() => Promise` Get the currently focused cell. #### Returns Type: `Promise` ### `getPlugins() => Promise` Get all active plugins instances #### Returns Type: `Promise` ### `getProviders() => Promise` Get all providers for grid Useful for external grid integration #### Returns Type: `Promise` ### `getSelectedRange() => Promise<(RangeArea & AllDimensionType) | null>` Get the currently selected Range. #### Returns Type: `Promise<(RangeArea & AllDimensionType) | null>` ### `getSource(type?: DimensionRows) => Promise` Get data from source #### Parameters | Name | Type | Description | | ------ | ---------------------------- | ----------- | | `type` | `DimensionRowPin \| "rgRow"` | | #### Returns Type: `Promise` ### `getSourceStore(type?: DimensionRows) => Promise>>` Provides access to rows internal store observer Can be used for plugin support #### Parameters | Name | Type | Description | | ------ | ---------------------------- | ---------------- | | `type` | `DimensionRowPin \| "rgRow"` | - type of source | #### Returns Type: `Promise>>` ### `getVisibleSource(type?: DimensionRows) => Promise` Get data from visible part of source Trimmed/filtered rows will be excluded #### Parameters | Name | Type | Description | | ------ | ---------------------------- | ---------------- | | `type` | `DimensionRowPin \| "rgRow"` | - type of source | #### Returns Type: `Promise` ### `refresh(type?: DimensionRows | "all") => Promise` Refreshes data viewport. Can be specific part as rgRow or pinned rgRow or 'all' by default. #### Parameters | Name | Type | Description | | ------ | ------------------------ | ----------- | | `type` | `DimensionRows \| "all"` | | #### Returns Type: `Promise` ### `refreshExtraElements() => Promise` Refresh extra elements. Triggers re-rendering of extra elements and functions. Part of extraElements and registerVNode methods. Useful for plugins. #### Returns Type: `Promise` ### `scrollToColumnIndex(coordinate?: number) => Promise` Scrolls viewport to specified column by index. #### Parameters | Name | Type | Description | | ------------ | -------- | ----------- | | `coordinate` | `number` | | #### Returns Type: `Promise` ### `scrollToColumnProp(prop: ColumnProp, dimension?: DimensionTypeCol) => Promise` Scrolls viewport to specified column by prop #### Parameters | Name | Type | Description | | ----------- | ------------------ | ----------- | | `prop` | `string \| number` | | | `dimension` | `"rgCol"` | | #### Returns Type: `Promise` ### `scrollToCoordinate(cell: Partial) => Promise` Scrolls view port to coordinate #### Parameters | Name | Type | Description | | ------ | ------------------------------------------------------- | ----------- | | `cell` | `{ x?: number \| undefined; y?: number \| undefined; }` | | #### Returns Type: `Promise` ### `scrollToRow(coordinate?: number) => Promise` Scrolls viewport to specified row by index. #### Parameters | Name | Type | Description | | ------------ | -------- | ----------- | | `coordinate` | `number` | | #### Returns Type: `Promise` ### `setCellEdit(rgRow: number, prop: ColumnProp, rowSource?: DimensionRows) => Promise` Open editor for cell. #### Parameters | Name | Type | Description | | ----------- | ---------------------------- | ----------- | | `rgRow` | `number` | | | `prop` | `string \| number` | | | `rowSource` | `DimensionRowPin \| "rgRow"` | | #### Returns Type: `Promise` ### `setCellsFocus(cellStart?: Cell, cellEnd?: Cell, colType?: string, rowType?: string) => Promise` Set focus range. #### Parameters | Name | Type | Description | | ----------- | -------- | ----------- | | `cellStart` | `Cell` | | | `cellEnd` | `Cell` | | | `colType` | `string` | | | `rowType` | `string` | | #### Returns Type: `Promise` ### `setDataAt({ row, col, colType, rowType, val, skipDataUpdate }: { row: number; col: number; val?: any; skipDataUpdate?: boolean; } & AllDimensionType) => Promise` Refreshes data at specified cell. Useful for performance optimization. No viewport update will be triggered. #### Parameters | Name | Type | Description | | ----- | ---------------------------------------------------------------------------------------------------- | ----------- | | `__0` | `{ row: number; col: number; val?: any; skipDataUpdate?: boolean \| undefined; } & AllDimensionType` | | #### Returns Type: `Promise` ### `updateColumnSorting(column: Pick, order: "asc" | "desc" | undefined, additive: boolean) => Promise` Update column sorting #### Parameters | Name | Type | Description | | ---------- | ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | | `column` | `{ prop: ColumnProp; cellCompare?: CellCompareFunc> \| undefined; }` | - column prop and cellCompare | | `order` | `"asc" \| "desc" \| undefined` | - order to apply | | `additive` | `boolean` | - if false will replace current order later passed to SortingPlugin | #### Returns Type: `Promise` ### `updateColumns(cols: ColumnRegular[]) => Promise` Update columns #### Parameters | Name | Type | Description | | ------ | -------------------------------------------------------- | ----------- | | `cols` | `ColumnRegular>[]` | | #### Returns Type: `Promise` ## Slots | Slot | Description | | ----------------------------------- | -------------- | | `"data-{column-type}-{row-type}."` | | | `"focus-{column-type}-{row-type}."` | | | `"footer"` | Footer slot. | | `"header"` | Header slot. | | `"viewport"` | Viewport slot. | ## Dependencies ### Depends on - [revogr-row-headers](https://rv-grid.com/guide/rowHeaders) - [revogr-header](https://rv-grid.com/guide/header) - [revogr-overlay-selection](https://rv-grid.com/guide/overlay) - [revogr-data](https://rv-grid.com/guide/data) - [revogr-temp-range](https://rv-grid.com/guide/selectionTempRange) - [revogr-focus](https://rv-grid.com/guide/selectionFocus) - [revogr-viewport-scroll](https://rv-grid.com/guide/scroll) - [revogr-scroll-virtual](https://rv-grid.com/guide/scrollable) - revogr-attribution - revogr-extra ### Graph ```mermaid graph TD; revo-grid --> revogr-row-headers revo-grid --> revogr-header revo-grid --> revogr-overlay-selection revo-grid --> revogr-data revo-grid --> revogr-temp-range revo-grid --> revogr-focus revo-grid --> revogr-viewport-scroll revo-grid --> revogr-scroll-virtual revo-grid --> revogr-attribution revo-grid --> revogr-extra revogr-row-headers --> revogr-data revogr-row-headers --> revogr-viewport-scroll revogr-row-headers --> revogr-header revogr-data --> vnode-html revogr-overlay-selection --> revogr-edit revogr-overlay-selection --> revogr-clipboard revogr-overlay-selection --> revogr-order-editor revogr-extra --> revogr-extra style revo-grid fill:#f9f,stroke:#333,stroke-width:4px ``` ---------------------------------------------- *Built with ❤️ by Revolist OU* --- # Revogrid Events Source: https://rv-grid.com/guide/api/events # Revogrid Events | Name | Type | Component | Description | | ---- | ---- | --------- | ----------- | | contentsizechanged | `"colPinEnd" \| "colPinStart" \| "rgCol" \| "rgRow" \| "rowPinEnd" \| "rowPinStart"` | revo-grid | New content size has been applied. The size excludes the header. Currently, the event responsible for applying the new content size does not provide the actual size. To retrieve the actual content size, you can utilize the `getContentSize` function after the event has been triggered. | | beforeedit | `BeforeSaveDataDetails>>` | revo-grid | Before the data is edited. To prevent the default behavior of editing data and use your own implementation, call `e.preventDefault()`. To override the edit result with your own value, set the `e.val` property to your desired value. | | beforerangeedit | `TModel` | revo-grid | Before applying range data, specifically when a range selection occurs. To customize the data and prevent the default edit data from being set, you can call `e.preventDefault()`. | | afteredit | `BeforeSaveDataDetails>> \| D \| K` | revo-grid | After data applied or range changed. | | beforeautofill | `{ type: DimensionRows; colType: DimensionCols; newRange: RangeArea; oldRange: RangeArea; mapping: OldNewRangeMapping; newData: { [newRowIndex: number]: DataType; }; }` | revo-grid | Before autofill is applied. To prevent the default behavior of applying the edit data, you can call `e.preventDefault()`. | | beforerange | `{ type: DimensionRows; colType: DimensionCols; newRange: RangeArea; oldRange: RangeArea; mapping: OldNewRangeMapping; newData: { [newRowIndex: number]: DataType; }; }` | revo-grid | Before autofill is applied. Runs before beforeautofill event. Use e.preventDefault() to prevent range. | | afterfocus | `FocusAfterRenderEvent>` | revo-grid | After focus render finished. Can be used to access a focus element through `event.target`. This is just a duplicate of `afterfocus` from `revogr-focus.tsx`. | | roworderchanged | `{ from: number; to: number; }` | revo-grid | Before the order of `rgRow` is applied. To prevent the default behavior of changing the order of `rgRow`, you can call `e.preventDefault()`. | | beforesorting | `{ column: ColumnRegular>; order: "asc" \| "desc"; additive: boolean; }` | revo-grid | By `SortingPlugin`
Triggered immediately after header click.
First in sorting event sequence. Ff this event stops no other event called.
Use `e.preventDefault()` to prevent sorting. | | beforesourcesortingapply | `{ type: DimensionRows; sorting?: SortingOrder \| undefined; }` | revo-grid | By `SortingPlugin`
Same as `beforesorting` but triggered after `beforeanysource` (when source is changed).
Use `e.preventDefault()` to prevent sorting data change. | | beforesortingapply | `{ column: ColumnRegular>; order: "asc" \| "desc"; additive: boolean; }` | revo-grid | By `SortingPlugin`
After `beforesorting`
Triggered after column data updated with new sorting order.
Use `e.preventDefault()` to prevent sorting data change. | | aftersortingapply | `{ sorting?: SortingOrder \| undefined; sortingColumns?: SortingColumnMap \| undefined; sortingOrder?: SortingColumnOrder \| undefined; types: DimensionRows[]; }` | revo-grid | By `SortingPlugin`
Triggered after sorting has been applied and completed.
Provides final sorting state and sorting column metadata when available. | | rowdragstart | `TModel` | revo-grid | This event is triggered when the row order change is started. To prevent the default behavior of changing the row order, you can call `e.preventDefault()`. To change the item name at the start of the row order change, you can set `e.text` to the desired new name. | | headerclick | `ColumnRegular>` | revo-grid | On header click. | | beforecellfocus | `BeforeSaveDataDetails>>` | revo-grid | Before the cell focus is changed. To prevent the default behavior of changing the cell focus, you can call `e.preventDefault()`. | | beforefocuslost | `null \| { model: any; cell: Cell; colType: DimensionCols; rowType: DimensionRows; column?: ColumnRegular> \| undefined; }` | revo-grid | Before the grid focus is lost. To prevent the default behavior of changing the cell focus, you can call `e.preventDefault()`. | | beforesourceset | `{ type: DimensionRows; source: DataType[]; }` | revo-grid | Before main source/rows data apply. You can override data source here | | beforeanysource | `{ type: DimensionRows; source: DataType[]; }` | revo-grid | Before data apply on any source type. Can be source from pinned and main viewport. You can override data source here | | aftersourceset | `{ type: DimensionRows; source: DataType[]; }` | revo-grid | After main source/rows updated | | afteranysource | `{ type: DimensionRows; source: DataType[]; }` | revo-grid | Emitted after each source update, whether from the pinned or main viewport. Useful for tracking all changes originating from sources in both the pinned and main viewports. | | beforecolumnsgather | `{ columns: (ColumnRegular> \| ColumnGrouping)[]; }` | revo-grid | Emitted before user column definitions are gathered into the internal column collection. Listeners can replace `detail.columns` to rewrite the raw column set before RevoGrid normalizes it. | | beforecolumnsset | `{ columns: Record>[]>; columnByProp: Record>[]>; columnGrouping: ColumnGroupingCollection; maxLevel: number; sort: Record>>; }` | revo-grid | Emitted before a column update is applied. Listeners can use this event to perform any necessary actions or modifications before the column update is finalized. | | beforecolumnapplied | `{ columns: Record>[]>; columnByProp: Record>[]>; columnGrouping: ColumnGroupingCollection; maxLevel: number; sort: Record>>; }` | revo-grid | Emitted before a column update is applied, after the column set is gathered and the viewport is updated. Useful for performing actions or modifications before the final application of the column update. | | aftercolumnsset | `{ columns: ColumnCollection; order: SortingOrder; }` | revo-grid | Column updated | | beforefilterapply | `{ collection: Record; }` | revo-grid | Emitted before applying a filter to the data source. Use e.preventDefault() to prevent cell focus change. Modify if you need to change filters. | | beforefiltertrimmed | `{ collection: Record; itemsToFilter: Record; }` | revo-grid | Emitted before applying a filter to the data source. Use e.preventDefault() to prevent the default behavior of trimming values and applying the filter. Modify the `collection` property if you want to change the filters. Modify the `itemsToFilter` property if you want to filter the indexes for trimming. | | beforetrimmed | `{ trimmed: Record; trimmedType: string; type: string; }` | revo-grid | Emitted before trimming values. Use e.preventDefault() to prevent the default behavior of trimming values. Modify the `trimmed` property if you want to filter the indexes for trimming. | | aftertrimmed | `any` | revo-grid | Emitted after trimmed values have been applied. Useful for notifying when trimming of values has taken place. | | viewportscroll | `D` | revo-grid | Emitted when the viewport is scrolled. Useful for tracking viewport scrolling events. | | beforeexport | `{ data: DataType[]; } & ColSource` | revo-grid | Before export Use e.preventDefault() to prevent export Replace data in Event in case you want to modify it in export | | beforeeditstart | `BeforeSaveDataDetails>>` | revo-grid | Emitted before editing starts. Use e.preventDefault() to prevent the default edit behavior. | | aftercolumnresize | `{ [index: number]: ColumnRegular>; }` | revo-grid | Emitted after column resizing. Useful for retrieving the resized columns. | | beforerowdefinition | `{ vals: any; oldVals: any; }` | revo-grid | Emitted before the row definition is applied. Useful for modifying or preventing the default row definition behavior. | | filterconfigchanged | `any` | revo-grid | Emitted when the filter configuration is changed | | sortingconfigchanged | `{ columns?: { prop: ColumnProp; order: Order; cellCompare?: CellCompareFunc \| undefined; }[] \| undefined; additive?: boolean \| undefined; }` | revo-grid | Emitted when the sorting configuration is changed SortingPlugin subsribed to this event | | rowheaderschanged | `any` | revo-grid | Emmited when the row headers are changed. | | beforegridrender | `any` | revo-grid | Emmited before the grid is rendered. | | aftergridrender | `any` | revo-grid | Emmited after the grid is rendered. | | aftergridinit | `any` | revo-grid | Emmited after the grid is initialized. Connected to the DOM. | | additionaldatachanged | `any` | revo-grid | Emmited after the additional data is changed | | afterthemechanged | `string` | revo-grid | Emmited after the theme is changed | | created | `any` | revo-grid | Emmited after grid created | | beforepaste | `{ raw: string; isHTML: boolean; event: ClipboardEvent; dataText: string; }` | revogr-clipboard | Paste 1. Fired before paste applied to the grid defaultPrevented - if true, paste will be canceled | | beforepasteapply | `{ raw: string; parsed: string[][]; dataText: string; event: ClipboardEvent; }` | revogr-clipboard | Paste 2. Fired before paste applied to the grid and after data parsed | | pasteregion | `string[][]` | revogr-clipboard | Paste 3. Internal method. When data region is ready pass it to the top. | | afterpasteapply | `{ raw: string; parsed: string[][]; dataText: string; event: ClipboardEvent; }` | revogr-clipboard | Paste 4. Fired after paste applied to the grid defaultPrevented - if true, paste will be canceled | | beforecut | `{ event: ClipboardEvent; }` | revogr-clipboard | Cut 1. Fired before cut triggered defaultPrevented - if true, cut will be canceled | | clearregion | `DataTransfer` | revogr-clipboard | Cut 2. Clears region when cut is done | | beforecopy | `{ event: ClipboardEvent; }` | revogr-clipboard | Copy 1. Fired before copy triggered defaultPrevented - if true, copy will be canceled | | beforecopyapply | `{ event: DataTransfer; data?: string[][] \| undefined; }` | revogr-clipboard | Copy Method 1. Fired before copy applied to the clipboard from outside. defaultPrevented - if true, copy will be canceled | | copyregion | `DataTransfer` | revogr-clipboard | Copy 2. Fired when region copied defaultPrevented - if true, copy will be canceled | | beforerowrender | `BeforeRowRenderEvent` | revogr-data | Before each row render | | afterrender | `{ type: DimensionRows; }` | revogr-data | When data render finished for the designated type | | beforecellrender | `BeforeCellRenderEvent, ColumnRegular>, ColumnProp>>` | revogr-data | Before each cell render function. Allows to override cell properties | | beforedatarender | `AllDimensionType` | revogr-data | Before data render | | dragstartcell | `DragStartEvent, ColumnRegular>>` | revogr-data | Event emitted on cell drag start | | celleditinit | `{ rgRow: number; rgCol: number; type: DimensionRows; prop: ColumnProp; val: any; preventFocus?: boolean \| undefined; }` | revogr-edit | Cell edit event initiator, first in the cellEdit event chain | | closeedit | `boolean \| undefined` | revogr-edit | Close editor event pass true if requires focus next | | filterChange | `MultiFilterItem` | revogr-filter-panel | | | resetChange | `number \| string` | revogr-filter-panel | | | beforefocusrender | `FocusRenderEvent` | revogr-focus | Before focus render event. Can be prevented by event.preventDefault(). If preventDefault used slot will be rendered. | | beforescrollintoview | `{ el: HTMLElement; }` | revogr-focus | Before focus changed verify if it's in view and scroll viewport into this view Can be prevented by event.preventDefault() | | afterfocus | `FocusAfterRenderEvent>` | revogr-focus | Used to setup properties after focus was rendered | | beforeheaderclick | `{ index: number; originalEvent: MouseEvent; column: ColumnRegular>; providers: ProvidersColumns; }` | revogr-header | On initial header click | | headerresize | `{ [x: string]: number; }` | revogr-header | On header resize | | beforeheaderresize | `ColumnRegular>[]` | revogr-header | On before header resize | | headerdblclick | `{ index: number; originalEvent: MouseEvent; column: ColumnRegular>; providers: ProvidersColumns; }` | revogr-header | On header double click | | beforeheaderrender | `{ column: VirtualPositionItem; additionalData: any; data: ColumnTemplateProp; range?: RangeArea \| null \| undefined; canResize?: boolean \| undefined; canFilter?: boolean \| undefined; renderOffset?: number \| undefined; onResize?(e: ResizeEvent): void; onClick?(data: InitialHeaderClick): void; onDblClick?(data: InitialHeaderClick): void; } & Partial>` | revogr-header | Before each header cell render function. Allows to override cell properties | | beforegroupheaderrender | `{ level: number; start: number; end: number; group: Group; providers: ProvidersColumns; additionalData: any; canResize?: boolean \| undefined; renderOffset?: number \| undefined; onResize?(e: ResizeEvent): void; } & Partial>` | revogr-header | Before each group header cell render function. Allows to override group header cell properties | | afterheaderrender | `ProvidersColumns` | revogr-header | After all header cells rendered. Finalizes cell rendering. | | columndragstart | `ColumnDragStartEventData` | revo-grid | Triggered when a column drag operation starts. Call preventDefault() to prevent the column move. | | columndragmousemove | `MouseEvent` | revo-grid | Fired while a column drag operation is moving. | | beforecolumndragend | `BeforeColumnDragEndEventData` | revo-grid | Fired before the column drag operation is applied. Call preventDefault() to reject the move. | | columndragend | `ColumnDragEventData` | revo-grid | Fired when the column drag operation completes. Includes reordered columns, physical order, and viewport type. | | beforerowresize | `RowResizeEventDetail` | revo-grid | Fired before a row-header resize gesture starts. Call preventDefault() to reject the gesture. | | rowresize | `RowResizeEventDetail` | revo-grid | Fired after each live row-height update. | | afterrowresize | `RowResizeEventDetail` | revo-grid | Fired after a row resize gesture commits. | | rowresizecancel | `RowResizeCancelEventDetail` | revo-grid | Fired after an interrupted row resize restores the original heights. | | rowdragstartinit | `TModel` | revogr-order-editor | Row drag started | | rowdragendinit | `{ rowType: DimensionRows; }` | revogr-order-editor | Row drag ended started | | rowdragmoveinit | `PositionItem & { rowType: DimensionRows; }` | revogr-order-editor | Row move started | | rowdragmousemove | `Cell & { rowType: DimensionRows; }` | revogr-order-editor | Row mouse move started | | rowdropinit | `{ from: number; to: number; rowType: DimensionRows; }` | revogr-order-editor | Row dragged, new range ready to be applied | | roworderchange | `{ from: number; to: number; rowType: DimensionRows; }` | revogr-order-editor | Row drag ended finished. Time to apply data | | beforecopyregion | `any` | revogr-overlay-selection | Before clipboard copy happened. Validate data before copy. To prevent the default behavior of editing data and use your own implementation, call `e.preventDefault()`. | | beforepasteregion | `any` | revogr-overlay-selection | Before region paste happened. | | celleditapply | `BeforeSaveDataDetails>>` | revogr-overlay-selection | Cell edit apply to the data source. Triggers datasource edit on the root level. | | beforecellfocusinit | `BeforeSaveDataDetails>>` | revogr-overlay-selection | Before cell focus. | | beforenextvpfocus | `Cell` | revogr-overlay-selection | Fired when change of viewport happens. Usually when we switch between pinned regions. | | setedit | `BeforeSaveDataDetails>>` | revogr-overlay-selection | Set edit cell. | | beforeapplyrange | `FocusRenderEvent` | revogr-overlay-selection | Before range applied. First step in triggerRangeEvent. | | beforesetrange | `any` | revogr-overlay-selection | Before range selection applied. Second step in triggerRangeEvent. | | setrange | `RangeArea & { type: MultiDimensionType; }` | revogr-overlay-selection | Set range. Third step in triggerRangeEvent. | | beforeeditrender | `FocusRenderEvent` | revogr-overlay-selection | Before editor render. | | selectall | `any` | revogr-overlay-selection | Select all cells from keyboard. | | canceledit | `any` | revogr-overlay-selection | Cancel edit. Used for editors support when editor close requested. | | settemprange | `null \| { type: string; area: RangeArea; }` | revogr-overlay-selection | Set temp range area during autofill. | | beforesettemprange | `{ tempRange: Nullable \| null; } & EventData & AllDimensionType` | revogr-overlay-selection | Before set temp range area during autofill. | | applyfocus | `FocusRenderEvent` | revogr-overlay-selection | Before cell get focused. To prevent the default behavior of applying the edit data, you can call `e.preventDefault()`. | | focuscell | `ApplyFocusEvent & FocusRenderEvent` | revogr-overlay-selection | Cell get focused. To prevent the default behavior of applying the edit data, you can call `e.preventDefault()`. | | beforerangedataapply | `FocusRenderEvent` | revogr-overlay-selection | Range data apply. | | selectionchangeinit | `{ type: DimensionRows; colType: DimensionCols; newRange: RangeArea; oldRange: RangeArea; mapping: OldNewRangeMapping; newData: { [newRowIndex: number]: DataType; }; }` | revogr-overlay-selection | Autofill data in range. First step in applyRangeWithData | | beforerangecopyapply | `{ type: DimensionRows; colType: DimensionCols; newRange: RangeArea; oldRange: RangeArea; mapping: OldNewRangeMapping; newData: { [newRowIndex: number]: DataType; }; }` | revogr-overlay-selection | Before range copy. | | rangeeditapply | `TModel` | revogr-overlay-selection | Range data apply. Triggers datasource edit on the root level. | | clipboardrangecopy | `RangeClipboardCopyEventProps` | revogr-overlay-selection | Range copy. | | clipboardrangepaste | `RangeClipboardPasteEvent>` | revogr-overlay-selection | Range paste event. | | beforekeydown | `{ original: KeyboardEvent; } & EventData` | revogr-overlay-selection | Before key up event proxy, used to prevent key up trigger. If you have some custom behaviour event, use this event to check if it wasn't processed by internal logic. Call preventDefault(). | | beforekeyup | `{ original: KeyboardEvent; } & EventData` | revogr-overlay-selection | Before key down event proxy, used to prevent key down trigger. If you have some custom behaviour event, use this event to check if it wasn't processed by internal logic. Call preventDefault(). | | beforecellsave | `any` | revogr-overlay-selection | Runs before cell save. Can be used to override or cancel original save. | | celledit | `{ rgRow: number; rgCol: number; type: DimensionRows; prop: ColumnProp; val: any; preventFocus?: boolean \| undefined; }` | revogr-overlay-selection | Runs when edit finished save started, first in chain event | | scrollview | `D` | revogr-row-headers | Scroll viewport | | ref | `ElementScroll` | revogr-row-headers | Register element to scroll | | scrollvirtual | `D` | revogr-scroll-virtual | Scroll event | | scrollviewport | `D` | revogr-viewport-scroll | Before scroll event | | resizeviewport | `{ dimension: DimensionType; size: number; rowHeader?: boolean \| undefined; }` | revogr-viewport-scroll | Viewport resize | | scrollchange | `{ type: DimensionType; hasScroll: boolean; }` | revogr-viewport-scroll | Triggered on scroll change, can be used to get information about scroll visibility | | scrollviewportsilent | `D` | revogr-viewport-scroll | Silently scroll to coordinate Made to align negative coordinates for mobile devices | | html | `{ html: string; vnodes: VNode[] \| null; }` | vnode-html | | *Built with ❤️ by Revolist OU* --- # RevoGrid Viewports Source: https://rv-grid.com/guide/viewports Description: Understand RevoGrid viewport architecture for virtual rows, virtual columns, pinned rows, pinned columns, dimensions, and scrolling behavior. # Understanding Viewports RevoGrid has pinned rows (top and bottom) and pinned columns (left and right), which leads to three different viewports for each type: ---

--- For rows, the viewports are: - `rowPinStart` - `rgRow` - `rowPinEnd` For columns, the viewports are: - `colPinStart` - `rgCol` - `colPinEnd` This structure was designed for a unified grid architecture, making the code easier to read and understand. However, this introduces some advanced concepts that need to be supported. Specifically, it means that different events will return virtual indexes instead of real ones. ## Understanding Virtual Indexes In RevoGrid, the concept of virtual indexes is crucial for efficiently managing the layout of the grid, especially when working with pinned rows and columns. These indexes allow the grid to optimize rendering and event handling, ensuring that the user experience remains smooth even with large datasets. ### Row Virtual Indexes For rows, the virtual indexes are structured as follows: - The first array represents the pinned rows at the top (`rowPinStart`). - The second array represents the main body of the grid rows (`rgRow`). - The third array represents the pinned rows at the bottom (`rowPinEnd`). For example, the virtual row indexes might look like this: ``` [ [0, 1, 2, ...], // Pinned rows at the top [0, 1, 2, 3, 4, ...], // Main body of the grid [0, 1, ...] // Pinned rows at the bottom ] ``` This structure indicates that when you interact with a cell in the grid, the event handling will refer to these virtual indexes instead of the actual indexes in your data source. For instance, if you are working with the main body of the grid and you access the first row, you will receive `rowIndex` of `0` from the second array, but this corresponds to the actual data index in your dataset. ### Column Virtual Indexes Similarly, for columns, the virtual indexes are organized to account for pinned columns: - The first set of indexes represents the pinned columns on the left (`colPinStart`). - The second set represents the main grid columns (`rgCol`). - The last set represents the pinned columns on the right (`colPinEnd`). The structure for columns would look like this: ``` [ [0, 1, ...], // Pinned columns on the left [0, 1, 2, 3, ...], // Main grid columns [0, 1, ...] // Pinned columns on the right ] ``` ### Implications of Using Virtual Indexes When working with events, it’s important to remember that every event dispatched from the grid will return these virtual indexes instead of the actual indexes from your dataset. This design choice simplifies event management but also requires developers to consider how they map these indexes back to their underlying data model. For example, if you have an event such as `beforeedit`, the event details may look like this: ```typescript export type BeforeSaveDataDetails = { prop: ColumnProp; model: DataType; val?: SaveData; rowIndex: number; // virtual row index colIndex: number; // virtual column index colType: DimensionCols; type: DimensionRows; }; ``` Here, `rowIndex` and `colIndex` refer to the virtual indexes, which means that if you want to retrieve the actual data from your source, you may need to perform additional calculations or mappings based on the grid’s layout. ## Why Ranges Stay Inside One Viewport Range coordinates are only complete when they are paired with their viewport types. A range area stores virtual coordinates: ```ts type RangeArea = { x: ColIndex; y: RowIndex; x1: ColIndex; y1: RowIndex; }; ``` The range event adds the row and column viewport types around those coordinates: ```ts type ChangedRange = { type: DimensionRows; colType: DimensionCols; newRange: RangeArea; oldRange: RangeArea; }; ``` This is why a single range selection, clipboard fill, or autofill operation should stay inside one row viewport and one column viewport. `x: 0` in `colPinStart` and `x: 0` in `rgCol` are different virtual coordinate systems. The same applies to `rowPinStart`, `rgRow`, and `rowPinEnd`. Autofill follows the same model. It reads the selected data from `providers.data.stores[type]` and resolves columns through `providers.column.stores[colType]`. If an autofill drag crossed from a pinned viewport into the main viewport, it would no longer be one rectangular `ChangedRange`; it would be several viewport-scoped ranges stitched together. For example, imagine a grid with one pinned top row and a vertically scrolled main viewport: - `rowPinStart` shows pinned row `0`. - `rgRow` is scrolled so the first visible main row is much lower in the dataset. - The user starts autofill from the pinned row and drags into a visible main row. If RevoGrid treated that as one range, the write target would be unclear. Should it fill only the cells that are visible on screen? Should it fill every main row between the pinned row and the scrolled row, including rows hidden behind the scroll gap? Or should the coordinates stay in the pinned row store, where the main viewport row does not exist? Each interpretation can surprise users and plugin authors in a different way. That stitching is a bad fit for the grid model because it hides where the operation actually writes, makes virtual indexes ambiguous, and can mix pinned and main data stores in one gesture. If a workflow needs to update pinned and main areas together, model it as explicit separate operations per viewport instead of one cross-viewport autofill. This is different from a spreadsheet such as Excel. Excel's Freeze Panes keeps rows or columns visible while another worksheet area scrolls, but the worksheet still has one continuous row and column address space. RevoGrid's pinned areas are separate row and column viewport stores, so the same visual gesture cannot be interpreted as one continuous autofill range without adding rules for the hidden rows and viewport boundaries. ## Practical Example Let’s say you have a grid with pinned rows and columns, and a user interacts with a cell in the main grid. When you handle the `beforeedit` event: ```ts revogrid.addEventListener('beforeedit', (event: HTMLRevoGridElementEventMap['beforeedit']) => { const { rowIndex, colIndex } = event.detail; console.log(rowIndex, colIndex); }) ``` You might receive: ```ts { rowIndex: 0, // This refers to the first row in the main grid (rgRow) colIndex: 1, // This refers to the second column in the main grid (rgCol) } ``` But physically it could be 2, 3, or 4 row and column indexes. If you want to get the actual data from your dataset, you would need to translate these virtual indexes back to your data model, taking into account any pinned rows or columns. In this type definition, `BeforeSaveDataDetails` includes information about the dimension type for both rows and columns, with indexes provided in a virtual coordinate system per viewport. While you typically won’t encounter this in standard usage, it's crucial to understand if you’re developing advanced plugins. ```ts interface HTMLRevoGridElementEventMap { //... "beforeedit": BeforeSaveDataDetails; //... } type BeforeSaveDataDetails = { prop: ColumnProp; model: DataType; val?: SaveData; rowIndex: number; // virtual row index colIndex: number; // virtual column index colType: DimensionCols; type: DimensionRows; }; ``` ### Dimension Types To clarify the dimension types used in RevoGrid, consider the following type definitions: ```typescript export type DimensionTypeRow = 'rgRow'; export type DimensionTypeCol = 'rgCol'; export type DimensionColPin = 'colPinStart' | 'colPinEnd'; export type DimensionRowPin = 'rowPinStart' | 'rowPinEnd'; export type DimensionType = DimensionTypeCol | DimensionTypeRow; export type DimensionCols = DimensionColPin | DimensionTypeCol; export type DimensionRows = DimensionTypeRow | DimensionRowPin; export type MultiDimensionType = DimensionCols | DimensionRows; ``` These types help in managing the various dimensions and their respective states within the grid, ensuring that your code can effectively handle both pinned and unpinned rows and columns. Understanding the viewport system in RevoGrid Pro is vital for developers looking to implement advanced features and plugins. By familiarizing yourself with the virtual indexes and the corresponding dimension types, you can ensure that your implementation remains robust and effective. As you develop your applications, keep these concepts in mind to harness the full potential of RevoGrid's capabilities. Read more about render in proxy items [here](https://rv-grid.com/guide/proxy-items) ## Index Types Explained 1. **Physical Indexes**: The actual position of items in the source data array 2. **Virtual Indexes**: The visible position of items in the viewport/UI ### Physical Indexes - These are the actual positions in the source data array (`source[]`) - They remain constant as long as the data source isn't modified - Used for direct data access and modifications - Stored in the `source` array of the data store ### Virtual Indexes - These represent the visible positions in the UI - Managed through the `items[]` array which maps virtual indexes to physical ones - Change dynamically based on scrolling, filtering, and grouping - Used for viewport rendering and user interactions ## Key Conversion Functions ### Physical to Virtual Index Conversion ```typescript // Returns the virtual index for a given physical index function getSourceItemVirtualIndexByProp(store, prop) { const items = store.get('items'); const source = store.get('source'); const physicalIndex = findIndex(source, { prop }); return items.indexOf(physicalIndex); } ``` ### Virtual to Physical Index Conversion ```typescript // Returns the physical index for a given virtual index function getPhysical(store, virtualIndex) { const items = store.get('items'); return items[virtualIndex]; } ``` ## Data Access Methods ### Getting Source Items 1. **By Virtual Index**: ```typescript function getSourceItem(store, virtualIndex) { const source = store.get('source'); return source[getPhysical(store, virtualIndex)]; } ``` 2. **All Visible Items**: ```typescript function getVisibleSourceItem(store) { const source = store.get('source'); return store.get('items').map(v => source[v]); } ``` ## Data Modification ### Updating Source Data 1. **By Virtual Index**: ```typescript function setSourceByVirtualIndex(store, modelByIndex, mutate = true) ``` - Updates data using virtual indexes as reference - `modelByIndex`: Object with virtual indexes as keys and new values - `mutate`: If true, triggers a re-render 2. **By Physical Index**: ```typescript function setSourceByPhysicalIndex(store, modelByIndex, mutate = true) ``` - Updates data using physical indexes directly - `modelByIndex`: Object with physical indexes as keys and new values - `mutate`: If true, triggers a re-render ## Use Cases 1. **Scrolling**: Virtual indexes change while physical indexes remain constant 2. **Data Updates**: Physical indexes are used for data modifications 3. **Rendering**: Virtual indexes determine what's visible in the viewport 4. **Sorting/Filtering**: Modifies the mapping between virtual and physical indexes ## Best Practices 1. Use virtual indexes when dealing with UI interactions 2. Use physical indexes when modifying the underlying data 3. Always use the appropriate conversion functions when switching between index types 4. Be aware that virtual indexes can change during operations like sorting or filtering ## Related guides - [Grid Performance and Virtualization](https://rv-grid.com/guide/performance) - [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control) - [Advanced Configuration](https://rv-grid.com/guide/advanced-configuration) - [API: RevoGrid](https://rv-grid.com/guide/api/revoGrid) Read more about render behavior in [proxy items](https://rv-grid.com/guide/proxy-items). --- # Data Grid Column Configuration Source: https://rv-grid.com/guide/column Description: Configure RevoGrid columns with properties for sizing, grouping, pinning, templates, readonly behavior, column types, and header options. # Column Configuration in Data Grid [Interface: ColumnRegular](https://rv-grid.com/guide/types/Interface.ColumnRegular) A vertical line in the grid that categorizes the data to be displayed. Columns in RevoGrid can be configured with features like sorting, filtering, and custom cell rendering. ```typescript const columns: ColumnRegular[] = [ { prop: 'id', name: 'ID' }, { prop: 'name', name: 'Name' }, { prop: 'age', name: 'Age' }, { prop: 'email', name: 'Email' }, ]; ``` :::tip Check [Interface: ColumnRegular](https://rv-grid.com/guide/types/Interface.ColumnRegular) for more information. ::: To set the size of a column in RevoGrid, you can use the `size`, `minSize`, and `maxSize` properties within your column definition. These properties allow you to control the width of each column, ensuring that your grid is displayed exactly as you need it. Here’s how you can set the size for a column: ## Column Size You can specify a fixed size for a column using the `size` property. This value is the width of the column in pixels. ```typescript const columns = [ { prop: 'id', name: 'ID', size: 100 }, // Column width is set to 100px { prop: 'name', name: 'Name', size: 150 }, // Column width is set to 150px { prop: 'age', name: 'Age', size: 80 }, // Column width is set to 80px ]; ``` ### Example: Column Sizes Here’s a full example of how you might set up your columns in a RevoGrid with specific sizes: ```typescript import { defineCustomElements } from '@revolist/revogrid/loader' defineCustomElements() const grid = document.querySelector('revo-grid') if (grid) { grid.columns = [ { prop: 'id', name: 'ID', size: 100 }, { prop: 'name', name: 'Name', size: 150 }, { prop: 'age', name: 'Age', size: 80 }, ] grid.source = [ { id: 1, name: 'Alice', age: 30 }, { id: 2, name: 'Bob', age: 25 }, { id: 3, name: 'Charlie', age: 35 }, ] } ``` In this example: - The `ID` column has a fixed width of 100px. - The `Name` column has a base width of 150px. - The `Age` column has a base width of 80px. ## Advanced Column Features RevoGrid offers advanced cell features, including: - [Column Selection](https://rv-grid.com/guide/column/selection.pro) - [Column Spanning](https://rv-grid.com/guide/column/span.pro) - [Advanced Column Stretching](https://rv-grid.com/guide/column/stretch.pro) - [Other Features](https://rv-grid.com/pro) --- # Autosize feature Source: https://rv-grid.com/guide/column/autosize # Autosize feature Autosize is aiming to provide intuitive functionality of content dependent entities. Meanwhile some limitations applied. ## Column autosize In order to achieve column autosize support you have to set `autoSizeColumn` grid property. `autoSizeColumn` accept different options. The easiest way to start with to use excel like option: `autoSizeColumn = true` (by default it's `false`). Based on this option every column which has `autoSize: true` property can be recalculated on column header separator double click. ### Quick start ```js // define autosize per column, if you don't use advance config option allColumns (read below section #Advance usage) const columns = [{ prop: 'myField', autoSize: true }]; const rows = [{ 'myField': 'my long-long field' }]; const grid = document.querySelector('revo-grid'); grid.autoSizeColumn = true; grid.source = rows; grid.columns = columns; ``` ### Advance usage `autoSizeColumn` can be set up as a config object with optional parameters. ```js grid.autoSizeColumn = { mode: 'autoSizeOnTextOverlap' }; ``` ``` ts type AutoSizeColumnConfig = { // ui behavior mode mode?: ColumnAutoSizeMode; /** * autoSize for all columns * if allColumnes true all columns treated as autoSize, worse for performance * false by default */ allColumns?: boolean; /** * assumption per characted size * improves performance * by default defined as 7px per char, can be changed in this config */ letterBlockSize?: number; /** make size calculation exact * by default it based on assumption each character takes some space defined in letterBlockSize */ preciseSize?: boolean; }; ``` ### Brief modes description Column autosize comes in different variation based on user necessity. Each mode has it's own benefits and downsides: ```ts enum ColumnAutoSizeMode { // increases column width on header click according the largest text value headerClickAutosize = 'headerClickAutoSize', // increases column width on data set and text edit, decreases performance autoSizeOnTextOverlap = 'autoSizeOnTextOverlap', // increases and decreases column width based on all items sizes, worst for performance autoSizeAll = 'autoSizeAll' } ``` Visit our [demo](https://rv-grid.com/demo/) for real live sample. ::: warning Currently AutoSize works in Beta mode. Only text autosize supported. Mapped values and custom renders can't be autosized at this moment and require different plugin approach based on per column prerender. ::: ::: tip It's recommended to check autoSizeColumn.ts plugin for better understanding of all options. ::: --- # Column Header Template Source: https://rv-grid.com/guide/column/header.template # Column Header Template [Interface: ColumnRegular](https://rv-grid.com/guide/types/Interface.ColumnRegular) [Type: ColumnTemplateFunc](https://rv-grid.com/guide/types/TypeAlias.ColumnTemplateFunc) This article explaines how to use custom header function to display HTML content in a header. This is a powerful feature. `Remember` to escape any HTML code that could be used for XSS attacks. :::tip Check [Type: ColumnTemplateFunc](https://rv-grid.com/guide/types/TypeAlias.ColumnTemplateFunc) for more information. ::: ```ts const columns: ColumnRegular[] = [ { name: 'Person name', prop: 'name', // use this to return custom html per column columnTemplate: ( createElement: HyperFunc, props: ColumnTemplateProp, additionalData?: any ) => { return createElement( 'span', { style: { color: 'red', }, }, column.name ) }, }, ] ``` ## Using Keys in Header Templates > [!IMPORTANT] > **Keys are essential for VNode reconciliation.** When rendering lists or dynamic content, always provide unique keys to help the virtual DOM accurately identify, track, and update nodes. Use keys thoughtfully, as incorrect usage can lead to inefficient updates or unexpected behavior. When rendering multiple child elements in a header template, provide unique keys: ```ts const columns: ColumnRegular[] = [ { name: 'Actions', prop: 'actions', columnTemplate: ( createElement: HyperFunc, props: ColumnTemplateProp, additionalData?: any ) => { const actions = ['sort', 'filter', 'settings']; return createElement( 'div', { key: `header-${props.column.name}` }, actions.map((action, index) => createElement( 'button', { key: `action-${props.column.name}-${action}`, class: `action-control action-${action}`, }, action ) ) ); }, }, ] ``` --- # Header Properties Source: https://rv-grid.com/guide/column/properties # Header Properties [Interface: ColumnRegular](https://rv-grid.com/guide/types/Interface.ColumnRegular) [Type: ColPropertiesFunc](https://rv-grid.com/guide/types/TypeAlias.ColPropertiesFunc) Attributes or settings applied to column headers, influencing their behavior and presentation, such as [width, visibility, and events](https://rv-grid.com/guide/types/TypeAlias.CellProps). ```ts const columns: ColumnRegular[] = [{ name: 'Person name', prop: 'name', // apply this for custom properties columnProperties: ({ prop }: ColumnRegular): CellProps => { return { style: { color: 'red', }, class: { bank: true, }, } }, }] ``` --- # Readonly Source: https://rv-grid.com/guide/column/readonly # Readonly [ColumnDataSchemaModel](https://rv-grid.com/guide/types/TypeAlias.ColumnDataSchemaModel) [ReadOnlyFormat](https://rv-grid.com/guide/types/TypeAlias.ReadOnlyFormat) To use the `readonly` property in RevoGrid, you can set it either as a boolean value or as a function that returns a boolean value based on the provided `ColumnDataSchemaModel`. ### Using `readonly` as a Boolean If you want the entire column to be read-only, you can set the `readonly` property to `true` for that column. ```javascript const columns = [ { prop: 'name', name: 'Name', readonly: true, // This column is read-only }, { prop: 'age', name: 'Age', }, ] const data = [ { name: 'John', age: 30 }, { name: 'Jane', age: 25 }, ] ``` ### Using `readonly` as a Function If you want to conditionally set the `readonly` property based on the column data, you can provide a function that returns a boolean value. ```javascript const columns = [ { prop: 'name', name: 'Name', readonly: (params) => { // Make the cell read-only if the name is 'John' return params.model.name === 'John' }, }, { prop: 'age', name: 'Age', }, ] const data = [ { name: 'John', age: 30 }, { name: 'Jane', age: 25 }, ] ``` In this example, the `name` column will be read-only for rows where the `name` is 'John'. For other rows, it will be editable. ### Example with Both Approaches Here is an example combining both approaches for different columns: ```javascript const columns = [ { prop: 'name', name: 'Name', readonly: true, // Entire column is read-only }, { prop: 'age', name: 'Age', readonly: (params) => { // Make the cell read-only if the age is greater than 28 return params.model.age > 28 }, }, ] const data = [ { name: 'John', age: 30 }, { name: 'Jane', age: 25 }, ] ``` ### Complete Example in Context Here’s how you might integrate this into a full RevoGrid component in a React application: ```js const App = () => { const columns = [ { prop: 'name', name: 'Name', readonly: true, // Entire column is read-only }, { prop: 'age', name: 'Age', readonly: (params) => { // Make the cell read-only if the age is greater than 28 return params.model.age > 28 }, }, ] const data = [ { name: 'John', age: 30 }, { name: 'Jane', age: 25 }, ] } export default App ``` This example demonstrates how to configure columns to be read-only either entirely or based on specific conditions using RevoGrid's `readonly` property. --- # Column Ordering Source: https://rv-grid.com/guide/column/order # Column Ordering The Column Ordering plugin allows users to reorder columns through a simple drag-and-drop interface, providing enhanced control over grid layout. This feature can be enabled by setting the `canMoveColumns` property to `true`. ## Key Events: - **`columndragstart`**: Triggered when a column drag operation starts. You can use this event to conditionally prevent certain columns from being moved. The event detail is the column definition being dragged. - **`columndragmousemove`**: Fired during the drag operation, allowing you to track the movement of the column. - **`beforecolumndragend`**: Fired before the drag operation is applied. This event is cancelable; call `event.preventDefault()` to reject the move. - **`columndragend`**: Fired when the column drag operation is completed. Use `event.detail.columns` or `event.detail.order` to read and save the final column order for the affected viewport. :::tip `roworderchanged` is only for row drag-and-drop. Column drag-and-drop uses the `columndrag*` plugin events above. ::: ## Example Usage Here’s an example of how to set up and use the Column Ordering plugin in RevoGrid: ```javascript import { defineCustomElement } from '@revolist/revogrid/standalone'; defineCustomElement(); // Define your grid columns const columns = [ { name: 'ID', prop: 'id' }, { name: 'Name', prop: 'name' }, { name: 'Price', prop: 'price' } ]; // Initialize RevoGrid const grid = document.querySelector('revo-grid'); if (grid) { grid.source = [ { id: 1, name: 'Apple', price: 1.2 }, { id: 2, name: 'Banana', price: 0.5 }, { id: 3, name: 'Cherry', price: 2.0 } ]; grid.columns = columns; // Enable column movement grid.canMoveColumns = true; // Event listener to prevent certain columns from being moved grid.addEventListener('columndragstart', (e) => { const { detail } = e; if (detail.prop === 'id') { e.preventDefault(); // Prevent moving the 'ID' column } }); // Optional: validate the target before the move is applied grid.addEventListener('beforecolumndragend', (e) => { const { newItem, newPosition } = e.detail; if (newItem?.prop === 'id' || newPosition.itemIndex === 0) { e.preventDefault(); } }); // Save the final order after the move is applied grid.addEventListener('columndragend', (e) => { const order = e.detail.columns.map(({ prop }) => prop); localStorage.setItem('revogrid:column-order', JSON.stringify(order)); console.log('Column order changed in viewport:', e.detail.type, order); }); } ``` ## Customization and Control In the example above: - The `canMoveColumns` property is set to `true` to enable the column drag-and-drop feature. - The `columndragstart` event listener checks if the column being dragged is the 'ID' column. If it is, the drag operation is prevented by calling `e.preventDefault()`. - The `beforecolumndragend` event can cancel a specific drop target before the internal column order is updated. - The `columndragend` event runs after the internal order is updated. Use `event.detail.columns` to get the reordered columns for the affected viewport and persist them to local storage, user settings, or your backend. ## Persisting and Restoring Order A common pattern is to save only the `prop` sequence from `columndragend.detail.columns`, then sort your application-level column definitions before assigning them back to the grid on the next load. ```ts const savedOrder = JSON.parse( localStorage.getItem('revogrid:column-order') || '[]', ) as string[]; const orderIndex = new Map(savedOrder.map((prop, index) => [prop, index])); grid.columns = [...columns].sort((a, b) => { const left = orderIndex.get(String(a.prop)) ?? Number.MAX_SAFE_INTEGER; const right = orderIndex.get(String(b.prop)) ?? Number.MAX_SAFE_INTEGER; return left - right; }); ``` For pinned columns, `columndragend.detail.type` identifies the affected column viewport: `rgCol`, `colPinStart`, or `colPinEnd`. If your application stores pinned and regular column order separately, use that value to update only the affected region. --- # Pin/Freeze (Fixed columns) Source: https://rv-grid.com/guide/column/pin # Pin/Freeze (Fixed columns) [Interface: ColumnRegular](https://rv-grid.com/guide/types/Interface.ColumnRegular) [Type: DimensionColPin](https://rv-grid.com/guide/types/TypeAlias.DimensionColPin) :::warning Be aware that pinning columns and rows introduces virtual indexes to the grid. Please read more in the [Viewports section](https://rv-grid.com/guide/viewports). ::: Allows columns to be fixed or "pinned" to one side of the grid, remaining visible as the user scrolls horizontally through other columns. ``` ts const columns = [ { name: 'First Name', prop: 'firstName', }, { name: 'Status', prop: 'status', pin: 'colPinStart', }, { name: 'Age', prop: 'age', pin: 'colPinEnd', }, ]; ``` ## JavaScript Column Pin and Freeze :::preview #demo-overview .rv-overview :path /demo/js/js.column.pin.example ::: ::: details Source code [Git](https://github.com/revolist/revogrid-docs/tree/main/demo/js/js.column.pin.example.ts) ::: code-group <<< @/demo/js/js.column.pin.example.ts#snippet ::: --- # Column Grouping Source: https://rv-grid.com/guide/column/grouping # Column Grouping [Interface: ColumnGrouping](https://rv-grid.com/guide/types/Interface.ColumnGrouping) Column grouping creates stacked headers by placing related columns under a shared parent header. Use it when several fields belong to the same business concept, for example `Personal` details with `First Name`, `Last Name`, and `Age` below it. Groups are declared directly in the `columns` array. A regular column has a `prop`; a grouped column has `children`. Grouped columns can be nested, so the header can have as many levels as your layout needs. ## JavaScript Column Grouping ## Basic structure ```ts import type { ColumnGrouping, ColumnRegular } from '@revolist/revogrid' const columns: (ColumnGrouping | ColumnRegular)[] = [ { name: 'Personal', children: [ { name: 'First Name', prop: 'firstName' }, { name: 'Last Name', prop: 'lastName' }, ], }, { name: 'Project', prop: 'project' }, ] ``` In this example `Personal` is only a header group. The leaf columns, `First Name` and `Last Name`, are still the columns bound to row data. ## Nested groups Use nested `children` arrays when a header needs more than one grouping level. RevoGrid calculates the header depth from the column tree and aligns regular columns with grouped columns automatically. <<< @/demo/js/js.column.group.example.ts#columns ## When to use column groups - Group related fields so wide datasets are easier to scan. - Create multi-level headers for reports, financial tables, schedules, and operational dashboards. - Keep column definitions declarative instead of manually composing header rows. - Combine groups with regular column features such as sizing, sorting, pinning, templates, and filtering on the leaf columns. ## Notes - A grouped column should use `children`; a leaf column should use `prop`. - Sorting, filtering, editing, and data mapping apply to leaf columns. - Header templates can still be used on regular leaf columns. For group header customization, use the group/header render hooks exposed by the header API. - Column groups are a core feature and work in Community, Pro Lite, and Pro Advanced. ## Pro grouping features RevoGrid Pro extends grouping from static headers into interactive analysis, layout control, and grouped summaries. ### Column collapse and expand [Column Collapse & Expand](https://rv-grid.com/pro) lets users drill down through grouped columns by collapsing less relevant branches and expanding them again when detail is needed. It is designed for wide grouped datasets where users need a compact working view without removing the underlying column structure. ### Column hide [Column Hide](https://rv-grid.com/pro) can be used with grouped layouts to create focused views of a dataset. Hide low-priority fields while keeping the remaining grouped headers readable and aligned. ### Row grouping drag and drop [Row Grouping Drag and Drop](https://rv-grid.com/pro) adds an interactive grouping panel where users can drag columns to group rows by one or more fields. Use it when grouping should be controlled by the user at runtime instead of being fixed in the grid configuration. ### Grouping aggregation [Grouping Aggregation](https://rv-grid.com/pro) adds summary values to grouped data, such as sum, average, count, min, or max. It is useful for grouped reports, financial summaries, and operational dashboards where each group needs an immediate total or metric. ### Pivot row and column grouping [Pivot Table](https://rv-grid.com/pivot) builds analytical row and column groups from dimensions and measures. It adds generated column groups, hierarchical rows, subtotals, grand totals, drill-down state, and grouped aggregate values for OLAP-style reporting. --- # RevoGrid Column Types and Column Formats Source: https://rv-grid.com/guide/column/types Description: Configure reusable RevoGrid column types for string, number, select, date, custom editors, cell templates, parsers, and shared data grid formatting. # Column Types and Formats Column types let you package column behavior once and reuse it across your grid. A type can define formatting, sizing, read-only rules, custom editors, cell templates, parsers, sorting behavior, and any other reusable column option. Use column types when several columns should behave the same way, or when a column needs a richer editor such as a number formatter, select dropdown, or date picker. ## How column types work RevoGrid exposes two related APIs: - `columnTypes` is a map of reusable type definitions registered on the grid. - `columnType` is the name used by a column to apply one of those definitions. Column settings are merged with the selected type. If the same option exists in both places, the column definition can override the shared type for that column. [Type: ColumnTypes](https://rv-grid.com/guide/types/TypeAlias.ColumnTypes) [Interface: ColumnType](https://rv-grid.com/guide/types/Interface.ColumnType) [Interface: ColumnRegular](https://rv-grid.com/guide/types/Interface.ColumnRegular) ```ts const grid = document.querySelector('revo-grid') grid.columnTypes = { money: { size: 140, readonly: false, cellTemplate: (createElement, props) => { const value = Number(props.model[props.prop] ?? 0) return createElement( 'span', { class: { 'money-cell': true, 'money-negative': value < 0 } }, new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', }).format(value) ) }, cellParser: (model, column) => Number(model[column.prop] ?? 0), }, } grid.columns = [ { prop: 'revenue', name: 'Revenue', columnType: 'money' }, { prop: 'cost', name: 'Cost', columnType: 'money', size: 110 }, ] ``` ## Built-in and plugin column formats The string format is available by default. Number, select, and date formats are distributed as optional packages so applications only ship the editors and formatters they actually use. | Format | Package | Best for | | --- | --- | --- | | [String](#string) | Built in | Plain text, IDs, labels, and default editable cells | | [Number](#number) | `@revolist/revogrid-column-numeral` | Numeric display, thousands separators, currency-like formatting | | [Select Dropdown](#select-dropdown) | `@revolist/revogrid-column-select` | Controlled choices, status values, lookup lists | | [Date](#date) | `@revolist/revogrid-column-date` | Date input, calendar picking, date strings | ## When to create a custom column type Create a custom type when the same column behavior appears in multiple places: - a currency or percentage format shared by many numeric columns - a reusable status style with custom classes - a read-only system field preset - a custom editor used by multiple columns - a parser that keeps filtering and sorting aligned with displayed values For one-off rendering, configure the column directly instead. See [Custom Cell Formats](https://rv-grid.com/guide/cell/custom-formats), [Cell Renderer](https://rv-grid.com/guide/cell/renderer), and [Cell Editor](https://rv-grid.com/guide/cell/editor). ## Register optional column type packages Optional column packages follow the same pattern: 1. Install the package. 2. Import the type plugin. 3. Register it in `columnTypes`. 4. Reference it from a column with `columnType`. ```ts import NumberColumnType from '@revolist/revogrid-column-numeral' const columnTypes = { numeric: new NumberColumnType('0,0'), } const columns = [ { prop: 'quantity', name: 'Quantity', columnType: 'numeric' }, ] ``` Framework wrappers use the same data shape. Pass `columns`, `source`, and `columnTypes` through your framework binding, or assign them directly to the `` element in plain JavaScript. ## Available column formats ### String String is the default RevoGrid column format. Use it for plain text, identifiers, labels, and any editable cell that does not need a specialized editor. No package or registration is required: ```ts const columns = [ { prop: 'name', name: 'Name' }, { prop: 'email', name: 'Email' }, ] ``` Values are read as text for display. If a column needs custom rendering, validation, parsing, or editing behavior, define those options directly on the column or move them into a reusable `columnTypes` preset.

### Number The number column type adds numeric formatting through the [revogrid-column-numeral](https://github.com/revolist/revogrid-column-numeral) package, based on [numeraljs](http://numeraljs.com). Use it for quantities, totals, prices, percentages, and other numeric values that should keep a consistent display format. The source value should be numeric or safely convertible to a number. The formatter controls how the value appears in the cell. #### Installation ::: code-group ```npm npm i @revolist/revogrid-column-numeral ``` ```pnpm pnpm add @revolist/revogrid-column-numeral ``` ```yarn yarn add @revolist/revogrid-column-numeral ``` ```bun bun add @revolist/revogrid-column-numeral ``` ::: #### Basic usage ```js import NumberColumnType from '@revolist/revogrid-column-numeral' // import library const plugin = { numeric: new NumberColumnType('0,0') } // create plugin entity const columns = [{ prop: 'num', columnType: 'numeric' }] // define column type const rows = [{ num: 1000 }] const grid = document.querySelector('revo-grid') grid.columnTypes = plugin grid.source = rows grid.columns = columns // '1,000' ``` #### Format examples ```ts const columnTypes = { integer: new NumberColumnType('0,0'), decimal: new NumberColumnType('0,0.00'), percent: new NumberColumnType('0.0%'), } const columns = [ { prop: 'orders', name: 'Orders', columnType: 'integer' }, { prop: 'revenue', name: 'Revenue', columnType: 'decimal' }, { prop: 'conversion', name: 'Conversion', columnType: 'percent' }, ] ``` For more formatting options, check the [plugin page](https://github.com/revolist/revogrid-column-numeral) and [numeraljs](http://numeraljs.com).

### Select Dropdown The select column type adds a dropdown editor through the [revogrid-column-select](https://github.com/revolist/RevoGrid-column-select) package, based on [revo-dropdown](https://github.com/revolist/revodropdown). Use it when users should choose from a controlled list of values, such as statuses, departments, categories, countries, or lookup table entries. Dropdown options can be represented as strings or objects. When using objects, configure `labelKey` and `valueKey` so the editor knows what to display and what to store. #### Installation ::: code-group ```npm npm i @revolist/revogrid-column-select ``` ```pnpm pnpm add @revolist/revogrid-column-select ``` ```yarn yarn add @revolist/revogrid-column-select ``` ```bun bun add @revolist/revogrid-column-select ``` ::: #### Basic usage 1. Import the select column type. 2. Define the dropdown source. 3. Register the type in `columnTypes`. 4. Set `columnType: 'select'` on the column. ```js // do Select class import import SelectTypePlugin from '@revolist/revogrid-column-select' const dropdown = { labelKey: 'label', valueKey: 'value', source: [ { label: 'According', value: 'a' }, { label: 'Over', value: 'b' }, { label: 'Source', value: 's' }, ], } const columns = [ { ...dropdown, prop: 'name', columnType: 'select', // column type specified as 'select' }, ] const rows = [{ name: 'New item' }, { name: 'New item 2' }] // register column type const plugin = { select: new SelectTypePlugin() } // apply data to grid per your framework approach ``` #### Option shape ```ts const dropdown = { labelKey: 'label', valueKey: 'value', source: [ { label: 'Draft', value: 'draft' }, { label: 'Approved', value: 'approved' }, { label: 'Archived', value: 'archived' }, ], } ``` Use the object form when the visible label and stored value should differ. #### Synchronize cell and dropdown templates Set `syncCellTemplate` to `true` when dropdown options should reuse the resolved cell template. This is opt-in; without the flag, options keep their existing text-only rendering. Object option fields are available on the synthetic row model passed to the cell template, which is useful for avatars, badges, and other metadata-driven renderers. ```ts const ownerType = new SelectTypePlugin() ownerType.cellTemplate = ownerCellTemplate ownerType.syncCellTemplate = true const columnTypes = { ownerSelect: ownerType } const columns = [ { prop: 'owner', columnType: 'ownerSelect', labelKey: 'name', valueKey: 'name', source: [ { name: 'Maya Chen', avatarIndex: 1 }, { name: 'Elias Novak', avatarIndex: 2 }, ], }, ] ``` If the column also provides an explicit dropdown `template`, that template takes precedence. #### Dynamic source `source` can be a synchronous function when options depend on the current row or on external state passed through `additionalData`. ```ts const columns = [ { prop: 'city', columnType: 'select', labelKey: 'label', valueKey: 'value', source: ({ model, additionalData }) => additionalData.citiesByCountry[model.country] ?? [], }, ] ``` The resolver receives the current cell model, prop, column, indexes, and `additionalData`. Async loading is not supported by this API.

### Date The date column type adds a calendar editor through the [revogrid-column-date](https://github.com/revolist/revogrid-column-date) package, based on [duetds-date-picker](https://github.com/duetds/date-picker). Use it for date strings or date values that should be edited with a date picker instead of plain text input. You can pass [duetds-date-picker](https://github.com/duetds/date-picker) properties through the column definition: ```js const columns = [ { prop: 'birthdate', columnType: 'date', direction: 'left', required: 'true', valueAsDate: 'true', }, ] ``` #### Installation ::: code-group ```npm npm i @revolist/revogrid-column-date ``` ```pnpm pnpm add @revolist/revogrid-column-date ``` ```yarn yarn add @revolist/revogrid-column-date ``` ```bun bun add @revolist/revogrid-column-date ``` ::: #### Basic usage 1. Import the date column type. 2. Register it in `columnTypes`. 3. Set `columnType: 'date'` on date columns. 4. Pass picker options on the column when needed. ```js // do import import Plugin from '@revolist/revogrid-column-date' const columns = [{ prop: 'birthdate', columnType: 'date' }] const rows = [{ birthdate: '2020-08-24' }, { birthdate: '2022-08-24' }] // register column type const columnTypes = { date: new Plugin() } // apply data to grid per your framework approach ``` Keep the date value format consistent across the column. If your application stores dates in a different shape than the editor displays, normalize the value before assigning `source` or handle conversion in your save workflow. # Date Column Demo
[![Edit RG - Date (Standalone)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-date-standalone-jwwwd8?file=%2Fsrc%2Findex.ts%3A27%2C62)

## RevoGrid Pro formats Available for richer data-entry, validation, and visualization workflows. Most Pro formats are registered through the same `columnTypes` pattern shown above, then applied with `columnType` on the target column. ### Checkbox editor Use a checkbox editor for boolean flags, approvals, task completion, row-level toggles, and other true/false values. It combines the renderer and editor into one compact cell interaction. ### Slider editor Use a slider editor for bounded numeric values such as scores, progress, priority, confidence, utilization, or percentage-like input where users need quick visual adjustment. ### Counter editor Use a counter editor for quantities, capacity, step-based values, and fast increment/decrement editing. It works well when values change in predictable steps. ### Timeline editor Use a timeline editor for date ranges, schedules, delivery windows, and project timelines. It gives users a visual date-range editing experience inside the grid. ### Progress line Use a progress line to show completion, utilization, SLA progress, budget usage, or any proportional value in a compact visual format. ### Progress line with value Use a progress line with value when users need both the visual progress bar and the exact readable number in the same cell. ### Sparkline Use a sparkline to show compact trends for time-series values, historical metrics, activity, or performance movement without opening a separate chart. ### Bar chart Use an inline bar chart for ranking, proportional comparison, and quick scanning of numeric values across many rows. ### Timeline Use a timeline format to display duration, phase, start/end positioning, or schedule context directly in grid cells. ### Rating star Use rating stars for reviews, quality scores, priority levels, satisfaction, or any small fixed-range rating. ### Badge Use badges for statuses, categories, severities, tags, workflow states, and other short labels that benefit from consistent visual treatment. ### Change Use a change format for deltas, gain/loss indicators, period-over-period movement, and positive/negative value changes. ### Thumbs Use thumbs for sentiment, approval, pass/fail, and quick feedback values. ### Pie chart Use an inline pie chart for part-to-whole values, compact distributions, and proportional breakdowns. ### Heat and cold map Use heat and cold maps to highlight value intensity, outliers, risk, performance bands, and low/high ranges with color. ### Conditional formatting Use conditional formatting for rule-based styles such as thresholds, alerts, exceptions, and state-dependent highlighting. ### Multi-cell formatting Use multi-cell formatting when different cells in the same column need different renderers, editors, or styles based on row data or custom conditions. ### Reference data Use reference data when the stored value is an ID, code, or key, but the user should see a readable label from a lookup source. ### Connected fields Use connected fields when values in one column depend on another column, or when edits should update linked cell behavior across the row. ### Cell validation Use cell validation to highlight invalid cells and prevent bad edits from becoming part of the data set. ### Input validation Use input validation to validate editor input before committing it to the grid, especially for constrained values, required fields, and business rules. See [RevoGrid Pro](https://rv-grid.com/pro/) and the [Feature Comparison](https://rv-grid.com/pro/feature-table) for plan availability and demos. ## Practical tips - Register `columnTypes` before assigning columns when possible, especially during initial grid setup. - Keep the data shape stable: `prop` must match a key in the row object. - Use `cellParser` when filtering should operate on a normalized value instead of formatted text. - Use column-level options to override a shared type for a single column. - Keep optional plugins out of the bundle until you need their editors or formatters. ## Troubleshooting If a type does not apply, check that the key in `columnTypes` exactly matches the column `columnType` value. If a plugin editor does not open, confirm that the package is installed, imported, and registered as an instance where the plugin expects one, for example `new NumberColumnType('0,0')`. If displayed values and filtering behave differently, add a `cellParser` to return the value that filter logic should use. Check the [live demos](https://rv-grid.com/demo/) for working grid examples, or use [Column Configuration](https://rv-grid.com/guide/column/) for the full list of column options. --- # Column Stretching in Data Grid Source: https://rv-grid.com/guide/column/stretch # Column Stretching in Data Grid The Column Stretch feature allows you to automatically expand the last column ([or any, or all columns](https://rv-grid.com/guide/column/stretch.pro)) to fill any remaining space in your grid. This ensures that your grid fully utilizes the available width, providing a more polished and professional appearance. ## Enabling Column Stretch To enable column stretching, simply set the `stretch` attribute to `"true"`. This will activate the feature, causing the last column to stretch and fill any unused space in the grid. ### Example Usage Here’s how to enable column stretching: ```html ``` ### How It Works With the `stretch` attribute enabled: - The last column will automatically adjust its width to fill the remaining space in the grid. - This feature is particularly useful when the total width of your columns doesn't match the width of the grid, ensuring that there are no gaps at the end. ### Benefits of Column Stretching - **Improved Aesthetics**: The grid appears fully utilized, eliminating any unnecessary white space. - **Responsive Design**: Automatically adapts to different screen sizes or container widths, making your grid more flexible. - **Simple Implementation**: Easily enable this feature with a single attribute, requiring no complex configuration. ## Conclusion The Column Stretch feature is a simple yet effective way to enhance the layout of your grid by ensuring the last column always fills the available space. By using the `stretch="true"` attribute, you can create grids that look clean, professional, and responsive with minimal effort. --- # Data Grid Cell Configuration Source: https://rv-grid.com/guide/cell Description: Set up Cell Configuration in Data Grid. The intersection point of a row and a column in the grid, capable of displaying and editing data. A cell can have custom renderers and editors, which are tightly coupled with the column properties. You can [customize cells using templates](https://rv-grid.com/guide/cell/renderer) to change their appearance or behavior. ## Cell Properties [Type: PropertiesFunc](https://rv-grid.com/guide/types/TypeAlias.PropertiesFunc) What are cell properties in RevoGrid. You can add various properties to cells, including tags, styles, classes, and events like `onClick`. ## Adding Custom Properties You can customize cells by defining properties within the `cellProperties` function. This function allows you to dynamically assign styles, classes, data attributes, and events based on the cell's data. ### Example Here's an example of how to use `cellProperties` to add custom styles, classes, data attributes, and events to cells: ```js const columns = [{ name: 'Person Name', prop: 'name', // Apply custom properties cellProperties: ({prop, model, data, column}) => { return { // Custom styles style: { color: model[prop] === 'John Doe' ? 'red' : 'black' }, // Custom classes class: { 'bank': data.isBankCustomer, 'vip': data.isVIP }, // Custom events onClick: (event) => { console.log(`Cell clicked: ${model[prop]}`); }, // Custom data attribute 'data-tooltip': model[prop] }; }, }]; const items = [ { name: 'John Doe', isBankCustomer: true, isVIP: false }, { name: 'Jane Smith', isBankCustomer: false, isVIP: true } ]; // Applying the columns and data source to the grid grid.columns = columns; grid.source = items; ``` ## Advanced Cell Features RevoGrid offers advanced cell features, including: - [Formula Support](https://rv-grid.com/guide/cell/formula) - [Cell Merge](https://rv-grid.com/guide/cell/merge) - [Other Features](https://rv-grid.com/pro) --- # RevoGrid Cell Renderer Source: https://rv-grid.com/guide/cell/renderer Description: Use RevoGrid cell templates to render custom cell content safely and efficiently across JavaScript and framework integrations. # Cell renderer [Interface: CellTemplate](https://rv-grid.com/guide/types/Interface.CellTemplate) [Interface: CellTemplateProp](https://rv-grid.com/guide/types/Interface.CellTemplateProp) This article explains how to use a [custom cell function](https://rv-grid.com/guide/types/Interface.CellTemplate) to display HTML content in a cell.
Alternatively, you can use [predefined column types](https://rv-grid.com/guide/column/types). > [!WARNING] > Remember to escape any HTML code that could be used for XSS attacks. :::tip RevoGrid's [API](https://rv-grid.com/guide/api/revoGrid) is consistent across all major frameworks. Transfer your experience and knowledge from one framework to another. :::
  • Angular logoAngular - Cell renderer for Angular applications.
  • React logoReact - Cell renderer for React applications.
  • Vue 2 logoVue 2 - Cell renderer for Vue 2 applications.
  • Vue 3 logoVue 3 - Cell renderer for Vue 3 applications.

> [!TIP] > Use [JSX](https://rv-grid.com/guide/jsx.template) to simplify your code and render HTML content. ```ts const columns: ColumnRegular[] = [ { name: 'Person name', prop: 'name', cellTemplate: ( createElement: HyperFunc, props: CellTemplateProp, additionalData?: any ) => { return createElement( 'span', { style: { color: 'red', }, }, props.model[props.prop] ) }, }, ] ``` ## Using Keys in Cell Templates > [!IMPORTANT] > **Keys are essential for VNode reconciliation.** When rendering lists or dynamic content, always provide unique keys to help the virtual DOM accurately identify, track, and update nodes. Use keys thoughtfully, as incorrect usage can lead to inefficient updates or unexpected behavior. ### Why Keys Matter Keys allow the virtual DOM to: - **Identify unique nodes** - Distinguish between different items even when content is similar - **Optimize updates** - Efficiently update only the nodes that have changed - **Preserve state** - Maintain component state when items are reordered or filtered ### Basic Key Usage When rendering multiple child elements, provide unique keys: ```ts const columns: ColumnRegular[] = [ { name: 'Tags', prop: 'tags', cellTemplate: ( createElement: HyperFunc, props: CellTemplateProp, additionalData?: any ) => { const tags = props.model[props.prop] || []; return createElement( 'div', null, tags.map((tag: any, index: number) => createElement( 'span', { key: tag.id || `tag-${props.rowIndex}-${index}`, class: 'tag', }, tag.label ) ) ); }, }, ] ``` ### Using Keys with Row and Column Identifiers For cells that may be reordered or filtered, combine row and column identifiers: ```ts const columns: ColumnRegular[] = [ { name: 'Status', prop: 'status', cellTemplate: ( createElement: HyperFunc, props: CellTemplateProp, additionalData?: any ) => { return createElement( 'div', { key: `cell-${props.rowIndex}-${props.colIndex}`, class: `status-${props.model[props.prop]}`, }, props.model[props.prop] ); }, }, ] ``` ### Best Practices 1. **Use stable identifiers** - Prefer IDs from your data model over array indices when possible 2. **Combine identifiers** - For cells, combine `rowIndex` and `colIndex` or use a unique row ID 3. **Keep keys consistent** - The same data item should always have the same key across renders 4. **Avoid random keys** - Never use `Math.random()` or similar as keys ### Example: Complex Cell with Multiple Elements ```ts const columns: ColumnRegular[] = [ { name: 'Details', prop: 'details', cellTemplate: ( createElement: HyperFunc, props: CellTemplateProp, additionalData?: any ) => { const details = props.model[props.prop] || []; const cellKey = `details-${props.rowIndex}-${props.colIndex}`; return createElement( 'div', { key: cellKey }, [ createElement('span', { key: `${cellKey}-title` }, props.model.name), createElement( 'ul', { key: `${cellKey}-list` }, details.map((detail: any, index: number) => createElement( 'li', { key: detail.id || `${cellKey}-item-${index}` }, detail.text ) ) ) ] ); }, }, ] ``` ## Related Pro features If you need richer visual cells such as charts, conditional formatting, heatmaps, or multi-renderer patterns, continue with [RevoGrid Pro](https://rv-grid.com/pro/) and [Feature Comparison](https://rv-grid.com/pro/feature-table). --- # RevoGrid Custom Cell Formats Source: https://rv-grid.com/guide/cell/custom-formats Description: Create custom RevoGrid cell formats with cell templates, cell properties, parsers, and reusable column types. # Custom Cell Formats Custom cell formats define how a value should look, behave, and be interpreted inside the grid. For a single column, configure formatting directly on the column definition. For reusable formats, define a `columnTypes` preset and reference it from any column with `columnType`. Use [Column Formats](https://rv-grid.com/guide/column/types) when you want to define custom formats per column or reuse the same format across many columns and cells. ## Format a single column Use `cellTemplate` when the display value needs custom markup or logic: ```ts const columns = [ { name: 'Total', prop: 'total', cellTemplate: (createElement, props) => { const value = Number(props.model[props.prop] ?? 0) return createElement( 'span', { class: { 'amount-positive': value >= 0, 'amount-negative': value < 0, }, }, new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', }).format(value) ) }, }, ] ``` Use `cellProperties` when the original value can stay as text, but the cell needs classes, styles, data attributes, or events: ```ts const columns = [ { name: 'Status', prop: 'status', cellProperties: ({ model, prop }) => ({ class: { 'status-cell': true, 'status-done': model[prop] === 'Done', 'status-blocked': model[prop] === 'Blocked', }, 'data-status': model[prop], }), }, ] ``` ## Reuse a format with `columnTypes` Define a format once in `grid.columnTypes`, then use `columnType` on every column that should inherit it: ```ts const currencyFormat = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', }) grid.columnTypes = { money: { size: 140, cellTemplate: (createElement, props) => { const value = Number(props.model[props.prop] ?? 0) return createElement( 'span', { class: { 'money-cell': true, 'money-negative': value < 0, }, }, currencyFormat.format(value) ) }, cellParser: (model, column) => Number(model[column.prop] ?? 0), }, } grid.columns = [ { name: 'Revenue', prop: 'revenue', columnType: 'money' }, { name: 'Cost', prop: 'cost', columnType: 'money' }, ] ``` Column settings override inherited `columnTypes` settings, so you can keep the shared format and adjust a specific column: ```ts grid.columns = [ { name: 'Revenue', prop: 'revenue', columnType: 'money' }, { name: 'Cost', prop: 'cost', columnType: 'money', size: 110 }, ] ``` ## Choosing the right option - Use `cellProperties` for classes, styles, data attributes, and event handlers. - Use `cellTemplate` for custom rendered content. - Use `cellParser` when filtering or data operations need a parsed value that differs from the displayed value. - Use `columnTypes` when the same format should be shared across multiple columns. See also [Cell Renderer](https://rv-grid.com/guide/cell/renderer), [Cell Editor](https://rv-grid.com/guide/cell/editor), and [Column Formats](https://rv-grid.com/guide/column/types). --- # Data Grid Cell Editors Source: https://rv-grid.com/guide/cell/editor Description: Build custom RevoGrid cell editors with render functions, save and close callbacks, editor lifecycle hooks, and TypeScript examples. # Cell editor in Data Grid `RevoGrid` provides a way to define your own editors. Or you can use [predefined column types](https://rv-grid.com/guide/column/types). In order to do so you have to define your class with render method. ## As a Function ```js function TextEditor(dataSchema, saveCallback, closeCallback) { return { element: null, // will be setup up after render editCell: null, // will be setup up after render /** * required, define custom component structure * @param createElement: (tagName: string, properties?: object, value?: any, children: Array) => VNode */ render(createElement) { return createElement('input'); }, componentDidRender() {}, // optional, called after component rendered disconnectedCallback() {}, // optional, called after component destroyed }; }; ``` ## As a Class ```ts class TextEditor { public element: Element|null = null; public editCell: EditCell|null = null; /** * @dataSchema: {ColumnDataSchemaModel} - data * @editCallback: { (val) => void } - callback for finishing edit */ constructor( public dataSchema: ColumnDataSchemaModel, saveCallback: (value: any) => void, closeCallback: () => void ) {} // optional, called after editor rendered componentDidRender() {} // optional, called after editor destroyed disconnectedCallback() {} /** * required, define custom component structure * @param createElement: (tagName: string, properties?: object, value?: any, children: Array) => VNode */ render(createComponent: HyperFunc) { return createComponent('input'); } /** * Optional method to get the current value from the editor * Called during auto-save process */ getValue() { // Return the current value from your editor return this.element?.value; } /** * Optional method called before auto-save is performed * Return false to prevent the auto-save * @param value The current value to be saved */ beforeAutoSave(value: any): boolean { // Return false to prevent save, true to allow return true; } /** * Optional method called before the editor is disconnected * Use this to cleanup any resources */ beforeDisconnect() { // Cleanup any resources before editor is destroyed } } ``` ## Editor Lifecycle and Save Behavior The editor component includes several important methods for handling save operations and lifecycle events: ### Auto-Save Process When auto-save is triggered (either through `saveOnClose` or programmatically): 1. The editor calls `getValue()` to retrieve the current value 2. If `beforeAutoSave()` is defined, it's called with the value: - Return `false` to prevent the save - Return `true` (or undefined) to allow the save 3. If save is allowed, the value is saved and the editor closes ### Save Options You can control save behavior through: - `saveOnClose` property - When true, editor attempts to save on close - Manual save - Call save callback directly from your editor - Cancel changes - Prevent save on close by calling `cancelChanges()` ## Use editor in the grid ```js const columns = [{ name: 'Person', prop: 'name', // define editor name editor: 'select', }]; const grid = div.querySelector('revo-grid'); // define editor component and name grid.editors = { 'select': customSelect }; ``` --- # Data & Rows in Data Grids Source: https://rv-grid.com/guide/row # Data & Rows in Data Grids A horizontal line in the grid representing a single data item from the source. RevoGrid offers extensive capabilities for managing rows and the data they contain. From customizing row appearances with class bindings to handling complex data structures, RevoGrid provides the tools you need to create dynamic and responsive data grids. ## Row Class Binding Row class binding allows you to dynamically apply CSS classes to individual rows based on the data they contain. This feature is useful for visually distinguishing rows that meet certain criteria, such as highlighting rows with specific statuses or applying alternate row colors. ### Using Row Class Binding To bind a CSS class to rows, you first need to define a property in your data source that will determine the row's class. You then use the `rowClass` attribute to tell RevoGrid which property to use for this purpose. ### Example: Applying Row Classes Here’s an example that demonstrates how to apply different CSS classes to rows based on the data: ```tsx // Define columns const columns = [{ name: 'Person', prop: 'name' }]; // Define data source with row classes const source = [ { name: 'Steve', myRowClass: 'blue' }, { name: 'John', myRowClass: 'green' } ]; // Render RevoGrid with row class binding return ''; ``` In this example: - The `myRowClass` property in the data source determines the CSS class applied to each row. - The `rowClass="myRowClass"` attribute in the RevoGrid component binds the `myRowClass` property to the rows, causing the grid to render rows with the corresponding classes. ### Customizing Row Styles You can define the styles for these classes in your CSS: ```css .blue { background-color: lightblue; } .green { background-color: lightgreen; } ``` With these styles applied, rows with `myRowClass: 'blue'` will have a light blue background, and rows with `myRowClass: 'green'` will have a light green background. ## Handling Complex Row Data RevoGrid can handle complex data structures, allowing you to manage rows that contain nested data, custom templates, or dynamic content. This flexibility is essential for creating grids that need to display diverse data types or require custom rendering logic. If your data contains nested objects or arrays, you can still bind this data to your grid's rows. Here’s an example: ```tsx const columns = [{ name: 'Person', prop: 'name' }, { name: 'Details', prop: 'details', cellTemplate: (h, data) => { return h('span', `Age: ${data.value.age}`); } }]; const source = [ { name: 'Steve', details: { age: 30 }, myRowClass: 'blue' }, { name: 'John', details: { age: 25 }, myRowClass: 'green' } ]; return ''; ``` In this example: - The `details.age` property accesses nested data within the `details` object for each row. - RevoGrid will correctly render the `age` property from the nested `details` object in the grid. ## Managing Row Visibility You may also want to manage the visibility of certain rows based on specific conditions. RevoGrid allows you to easily show or hide rows programmatically. ```tsx const grid = document.querySelector('revo-grid'); // Hide rows where the name is 'John' const filteredSource = source.filter(row => row.name !== 'John'); grid.source = filteredSource; ``` In this example: - The grid's data source is filtered to exclude rows where the `name` is 'John'. - The grid is then updated to display only the remaining rows. ### Trimmed Rows **Description:** The **Trimmed Rows** feature enables selective hiding of rows from the main dataset using physical `rgRow` indexes. By defining `trimmedRows` as a record of row indexes with boolean values, you can dynamically control which rows are visible in the grid. This is particularly useful for managing large datasets, where certain rows can be hidden based on conditions or user interactions, enhancing both performance and usability. **Example Usage:** ```tsx const grid = document.querySelector('revo-grid'); // Define rows to be hidden const trimmedRows = { 1: true, // Hides the row with index 1 5: true // Hides the row with index 5 }; // Apply trimmed rows to the grid grid.trimmedRows = trimmedRows; ``` **Explanation:** - **`trimmedRows`**: A record where each key represents the index of a row to hide (`true` indicates the row is hidden). - **Dynamic Visibility**: Adjust which rows are visible by updating the `trimmedRows` record as needed. ## Odd Row Highlighting The [`RowOddPlugin`](https://rv-grid.com/guide/row/odd.pro) allows you to automatically highlight odd-numbered rows in your data grid, enhancing the visual clarity and readability of your data. ## Master Rows The [`MasterRowsPlugin`](https://rv-grid.com/guide/row/master.pro) enables expandable rows within the grid, allowing you to display detailed or hierarchical data for each row. This is ideal for presenting nested information such as sub-rows, additional details, or hierarchical structures. **Benefits:** - **Performance Optimization**: Reduces the amount of visible data, which can enhance grid performance. - **Improved Usability**: Allows for better management of large datasets by hiding irrelevant or unneeded rows. ## Related guides - [Advanced Configuration](https://rv-grid.com/guide/advanced-configuration) - [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control) - [Understanding Viewports](https://rv-grid.com/guide/viewports) ## Related Pro features Need more row-focused workflows such as row select, row autosize, row order, transpose, or master-detail patterns? Continue with [RevoGrid Pro](https://rv-grid.com/pro/) and [Feature Comparison](https://rv-grid.com/pro/feature-table). --- # Row Resizing in JavaScript Data Grid Source: https://rv-grid.com/guide/row/resize Description: Let users resize rows from row-header or full-row edges, configure height limits, and respond to resize lifecycle events. Row resizing is an opt-in Core feature. Set the `resizeRow` grid property to let users drag the bottom edge of a row and change its height. Completed sizes are stored through the grid's row-definition pipeline. A resized height therefore stays attached to its physical source row when filtering or sorting changes the visible row order. ## Resize from row headers Set `resizeRow` and `rowHeaders` to `true` to display a resize edge at the bottom of each row header: ```js const grid = document.querySelector('revo-grid'); grid.rowHeaders = true; grid.resizeRow = true; ``` The boolean form uses the default minimum height of `20px` and has no maximum height. For static HTML, the boolean option can also be enabled with attributes: ```html ``` ## Resize from the full row edge Pass a configuration object with `fullRow: true` to make the resize edge available across rendered data rows. Users can then resize from the bottom edge of a row without requiring row headers. ```js const grid = document.querySelector('revo-grid'); grid.resizeRow = { fullRow: true, }; ``` `fullRow` extends the edge target across the row; the row body remains available for selection, editing, and other interactions. ## Configuration The object form accepts `RowResizeConfig`: ```ts import type { RowResizeConfig } from '@revolist/revogrid'; const resizeRow: RowResizeConfig = { minHeight: 28, maxHeight: 120, fullRow: true, }; grid.resizeRow = resizeRow; ``` | Option | Type | Default | Description | | --- | --- | --- | --- | | `minHeight` | `number` | `20` | Smallest height a user can assign. | | `maxHeight` | `number` | No limit | Largest height a user can assign. | | `fullRow` | `boolean` | `false` | Makes the resize edge available across data rows instead of only row headers. | Set `grid.resizeRow = false` to disable the interaction at runtime. The plugin remains registered internally, while its resize listeners and handles stay inactive. ## Selected rows If the grabbed row belongs to the active selected range, RevoGrid applies the same resulting height to every selected row. Grabbing a row outside the range resizes only that row. ## Resize events RevoGrid emits these events during a resize gesture: | Event | When it fires | | --- | --- | | `beforerowresize` | Before resizing starts. Call `preventDefault()` to cancel the gesture. | | `rowresize` | While pointer movement applies a live row height. | | `afterrowresize` | After the completed height is committed. | | `rowresizecancel` | When an active gesture is cancelled, for example with Escape or a configuration change. | Each event identifies the row dimension, grabbed row index, affected indexes, current size, previous sizes, and original pointer event. ```js grid.addEventListener('afterrowresize', event => { console.log(event.detail.index, event.detail.size); }); ``` ## Related guides - [Row Height](https://rv-grid.com/guide/row/height) - [Row Headers](https://rv-grid.com/guide/row/headers) - [Row Selection](https://rv-grid.com/guide/row/selection.pro) - [Filtering](https://rv-grid.com/guide/filters) --- # Pin or Freeze Rows in Data Grid Source: https://rv-grid.com/guide/row/pin Description: Use Pin or Freeze Rows in Data Grid to keep specific rows always visible at the top or bottom of the grid, even when the user scrolls through the rest of the data. :::warning Be aware that pinning columns and rows introduces virtual indexes to the grid. Please read more in the [Viewports section](https://rv-grid.com/guide/viewports). ::: Pinning (or freezing) rows in a Data Grid is a feature that allows you to keep specific rows always visible at the top or bottom of the grid, even when the user scrolls through the rest of the data. This is particularly useful for displaying headers, totals, or other key information that should remain accessible at all times. ## What are Pinned Rows? Pinned rows are rows that are fixed in place, separate from the main scrollable data set. You can pin rows to the top or bottom of your grid. These pinned rows are managed through separate data sources, which gives you full control over what is displayed in these fixed positions. ### Key Features: - **Pinned Top Rows**: These rows are fixed at the top of the grid and remain visible as you scroll through the rest of the data. - **Pinned Bottom Rows**: These rows are fixed at the bottom of the grid and also remain visible during scrolling. ## How to Implement Pinned Rows Implementing pinned rows is straightforward. You define separate data sources for the rows you want to pin and then assign these data sources to the `pinnedTopSource` and `pinnedBottomSource` properties of the grid. ### Example Here’s a simple example of how to pin rows at the top and bottom of your RevoGrid: ```javascript // Define the data sources for pinned rows const pinnedTopSource = [{ name: 'Dixon Hudson' }]; const pinnedBottomSource = [{ name: 'Weber Henderson' }]; // Initialize the RevoGrid const grid = document.querySelector('revo-grid'); // Assign the pinned rows grid.pinnedTopSource = pinnedTopSource; grid.pinnedBottomSource = pinnedBottomSource; ``` In this example: - The `pinnedTopSource` array contains the data for the row that will be pinned at the top of the grid. - The `pinnedBottomSource` array contains the data for the row that will be pinned at the bottom of the grid. - These rows will remain fixed in place while the rest of the grid's rows are scrollable. ## Use Cases for Pinned Rows Pinned rows are useful in a variety of scenarios, including: - **Headers and Labels**: Pinning headers or labels at the top of the grid to ensure that they are always visible. - **Totals and Summaries**: Displaying totals, averages, or other summary information in a pinned bottom row to keep key metrics in view. - **Sticky Notes or Comments**: Keeping important notes or comments accessible by pinning them to the top or bottom of the grid. ## Conclusion The ability to pin or freeze rows adds a significant layer of functionality to your data grid, enhancing the user experience by keeping critical information always visible. Whether you're displaying headers, summaries, or other key data, pinned rows ensure that your most important content remains front and center. Try implementing pinned rows in your grid setup today to see how they can improve your grid's usability and functionality. --- # Row Header in Data Grid Source: https://rv-grid.com/guide/row/headers Description: Learn how to customize row headers in Data Grid to display row numbers or use a fully custom template for advanced row header rendering. [Interface: RowHeaders](https://rv-grid.com/guide/types/Interface.RowHeaders) Row headers in RevoGrid are versatile and can be used to display row numbers, custom data, or even completely customized templates. This feature enables you to create an Excel-like grid with row numbers or to add meaningful row indicators to your grid. Row headers are an Excel-like feature that displays row numbers or other custom content on the left side of your grid. This feature is particularly useful for providing context and improving navigation within your data grid. By default, row headers are disabled, but they can be easily enabled and customized to fit your needs. ## Enabling Row Headers To enable row headers, set the `rowHeaders` property on the data table element. You can use a boolean to show row numbers or pass a custom `RowHeaders` object to define a template. ### Example: Default Row Headers ```typescript grid.rowHeaders = true; // Enable default row numbers grid.source = [ { name: 'Row 1' }, { name: 'Row 2' }, { name: 'Row 3' }, ]; ``` Or you can enable row headers directly in your HTML: ```html ``` In this configuration, the row headers will display default row numbers (e.g., 1, 2, 3). ## Customizing Row Headers In addition to simply displaying row numbers, RevoGrid allows you to customize row headers by treating them as additional fixed columns on the left side of the grid. This gives you full control over their appearance and behavior, similar to any other column in the grid. ### Customization Options When customizing row headers, you can use the same properties available for regular columns, such as `size`, `cellTemplate`, and more. #### Example: Setting Row Header Size You can set the size of the row headers to accommodate more content or to align with the overall design of your grid: ```js const grid = document.querySelector('revo-grid'); grid.rowHeaders = { size: 200 // Set the width of the row header column to 200px }; ``` #### Example: Customizing Row Header Content You can also use a custom cell template to display content other than just row numbers. This allows you to add icons, text, or even interactive elements to the row headers: ```js const grid = document.querySelector('revo-grid'); grid.rowHeaders = { size: 200, cellTemplate: (h, props) => h('div', `Row ${props.model[props.rowIndex].id}`) }; ``` In this example: - The `size` property sets the width of the row header column. - The `cellTemplate` function customizes the content of each row header, displaying "Row" followed by the ID of the row's data. ## Dynamic Row Header Updates The rowHeaders property can be dynamically updated at runtime. For example: ```typescript grid.rowHeaders = { size: 50, template: (h, { rowIndex }) => `Row ${rowIndex + 1}`, }; ``` ## Best Practices for Using Row Headers - **Use for Navigation**: Row headers make it easier for users to navigate large datasets by providing a constant reference point. - **Customize for Clarity**: If your grid contains complex data, consider customizing the row headers to display more than just row numbers, such as row identifiers or other relevant information. - **Balance with Grid Layout**: Ensure that the size and content of row headers do not overwhelm the main content of your grid. Adjust the size and styling to maintain a clean and functional layout. ## When to Use Custom Row Headers Custom row headers are ideal for: - Excel-like Numbering: Displaying row numbers to mimic Excel. - Status Indicators: Showing icons, badges, or status indicators. - Advanced Customization: Adding dynamic content like row metadata or progress indicators. ## Conclusion Row headers provide an Excel-like feature that enhances the usability of your data grid by offering a clear reference point on the left side of the table. Whether you need simple row numbers or more customized content, datagrid's row header functionality is flexible and easy to implement. By enabling and customizing row headers, you can improve the overall user experience, making your data grid more intuitive and easier to navigate. Try incorporating row headers into your grid setup to see how they can benefit your application. Learn more about the [RowHeaders interface](https://rv-grid.com/guide/types/Interface.RowHeaders). --- # Row Drag and Drop in Data Grid Source: https://rv-grid.com/guide/row/order Description: Use Row Drag and Drop in Data Grid to reorder rows dynamically through a drag-and-drop interface. The Data Grid **Row Drag and Drop** feature created to rearrange rows dynamically through a drag-and-drop interface. This functionality enhances the interactivity of your grid by allowing users to reorder rows easily, improving data organization and management. ## Key Features - **Drag-and-Drop Reordering**: - **Purpose**: Enables users to reorder rows by dragging a designated reordering cell. - **Benefit**: Provides an intuitive and interactive way to rearrange row positions within the grid. - **Special Reordering Cell**: - **Purpose**: Utilizes a specific cell to facilitate the dragging and dropping of rows. - **Benefit**: Simplifies the reordering process by clearly indicating the draggable area. - **Configuration**: - **Default State**: Row reordering is disabled by default to maintain initial grid configurations. - **Enable Reordering**: To activate row reordering, configure the `rowDrag` property in the column settings. ## Example Usage To enable row reordering in your grid, set the `rowDrag` property in the column configuration: ```tsx const grid = document.querySelector('revo-grid'); // Configure column property to enable row reordering grid.columns = [ { title: 'Name', field: 'name', rowDrag: true }, // Enables row reordering { title: 'Age', field: 'age' }, ]; ``` ## Explanation - **`rowDrag` Property**: Set to `true` in the column configuration where the reordering cell is specified. This activates the drag-and-drop functionality for rows. ## Benefits - **Enhanced Interactivity**: Allows users to rearrange rows according to their preferences, making data management more flexible. - **Improved Usability**: Offers an intuitive way for users to organize data without needing complex controls or additional tools. ## Implementation Tips - Ensure that the `rowDrag` property is set appropriately in your column configuration to enable the feature. - Customize the appearance and behavior of the reordering cell to match your grid’s design and user experience goals. ## Limitations & Pro Version - **Basic Functionality**: The standard row ordering feature provides fundamental drag-and-drop capabilities. - **Advanced Features**: For more advanced row ordering options, such as custom drag handles, advanced visual cues, or additional configuration settings, consider using the [Pro version](https://rv-grid.com/guide/row/order.pro) of RevoGrid. --- # Row Grouping in Data Grid Source: https://rv-grid.com/guide/row/grouping Description: Learn how to configure row grouping in RevoGrid using TypeScript. Easily group rows based on specific properties for better data organization and visualization. ## Grouping Configuration The grouping option takes an object with the props property, which specifies the columns to group by. In the example above, rows are grouped by the projectName property. ```typescript import { defineCustomElements } from '@revolist/revogrid/loader' import { type DataType } from '@revolist/revogrid' defineCustomElements() // Create grid element const grid = document.createElement('revo-grid') document.body.appendChild(grid) // Define columns const columns = [ { name: '🎰', prop: 'a', }, ] grid.columns = columns grid.source = ((rowsNumber) => { const result: DataType[] = [] const all = rowsNumber for (let j = 0; j < all; j++) { let row = j if (!result[row]) { result[row] = { id: row, projectName: j % 2 ? 'yes' : 'no', } } result[row]['a'] = `I am row ${row}` } return result })(100) grid.grouping = { props: ['projectName'] } ``` ## Vue 3 - Row Grouping
::: details Source code [Git](https://github.com/revolist/revogrid-docs/tree/main/demo/vue/vue.row-grouping.vue) ::: code-group <<< @/demo/vue/vue.row-grouping.vue ::: ### Example Grouping Output With the provided configuration: - Rows with projectName: 'yes' are grouped together. - Rows with projectName: 'no' are grouped separately. ## Dynamic Updates Grouping can be updated dynamically by modifying the grouping property of the grid. For example: ```typescript grid.grouping = { props: ['newGroupingProperty'] }; ``` For more details, check the [GroupingOptions interface](https://rv-grid.com/guide/types/TypeAlias.GroupingOptions). ## Related guides - [Advanced Configuration](https://rv-grid.com/guide/advanced-configuration) - [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control) - [Understanding Viewports](https://rv-grid.com/guide/viewports) ## Pro features ### [Row Grouping Drag and Drop](https://rv-grid.com/pro/) Let users drag columns into a grouping panel to create grouped rows interactively. This is useful when users need to change grouping dimensions while exploring operational or reporting data. ### [Grouping Aggregation](https://rv-grid.com/pro/) Add summary values such as sum, average, count, and other calculations to grouped rows. Use it when row groups need totals or rollups instead of only visual separation. ### [Pivot Table](https://rv-grid.com/pro/) Extend row grouping into multidimensional analysis with row dimensions, column dimensions, values, subtotals, grand totals, and drill-down state. This is the next step when grouping becomes an analytics workflow. ### [Hierarchical Data View](https://rv-grid.com/pro/) Represent parent-child row structures with expand and collapse behavior, hierarchy-aware visibility, and row integration. Use it when the row relationship is a tree rather than a flat group. ### [Row Advanced Drag and Drop](https://rv-grid.com/pro/) Enable advanced row movement with custom drag handles, drop behavior, and multi-item workflows. This helps when grouped or structured rows also need controlled reordering. ### [Row Checkbox Selection](https://rv-grid.com/pro/) Add checkbox-based row selection with keyboard interactions and bulk selection behavior. This is useful when users need to act on full groups or selected rows inside grouped datasets. --- # Accessibility in Data Grids Source: https://rv-grid.com/guide/wcag # Accessibility in Data Grids RevoGrid is committed to making data grids accessible to everyone, following international accessibility standards and best practices for Data Tables. This includes implementing keyboard navigation, support for screen readers, and ensuring that all interactive elements are easy to use for people with disabilities. ## Accessibility Guidelines Our Data Grid adheres to globally accepted accessibility standards such as WCAG (Web Content Accessibility Guidelines) and other regional regulations like ADA (Americans with Disabilities Act) and Section 508 in the US, as well as the European Accessibility Act (EAA). The aim is to support WCAG 2.1 Level AA, which is the most common target for organizations seeking to ensure their web applications are accessible. ### Key Guidelines Followed: - **WCAG (Web Content Accessibility Guidelines)**: Provides a comprehensive set of criteria for making web content accessible to a wide range of users, including those with disabilities. - **WAI-ARIA (Web Accessibility Initiative - Accessible Rich Internet Applications)**: Offers best practices for making web applications like RevoGrid accessible, particularly when it comes to complex interactive components like data grids. ## Keyboard Navigation Comprehensive keyboard navigation ensures that all users, including those who rely on keyboards instead of a mouse, can interact with the grid seamlessly. ### Key Navigation Features: - **Tab Sequence Management**: Following WAI-ARIA practices, grid ensures that only the relevant focusable elements are included in the tab sequence, making navigation intuitive. - **Arrow Keys**: Navigate between cell elements using the arrow keys, ensuring that users can move horizontally and vertically across the grid. - **Ctrl/CMD + A Keys**: Quickly all cells of the entire grid. - **Enter/Escape**: Select a cell or row for editing, or exit the edit mode using `Enter` or `Escape`. - **Ctrl/CMD + C/V Keys**: Copy and paste cells. ## Customizing Accessibility Features Grid events allow developers to customize and enhance the accessibility features to better suit their application’s needs. This can be done by intercepting the events and modifying the behavior as needed. - [Auto-Focus on Next Line](https://rv-grid.com/guide/wcag.next-focus.pro): This feature automatically moves the focus to the next row when the user reaches the last cell of the current row, making it easier for users to navigate through the grid. ## Density and Accessibility Themes are also provide options to adjust the density of rows and columns, making it easier to read and interact with the grid for users with different needs. ### Setting Density You can set the density of the grid using the `row-size` prop. This can be controlled programmatically or through the UI, providing flexibility based on user preferences. - **Standard Density 27px**: The default setting, offering standard Excel view. - **Compact Theme Density 32px**: Reduces the space between rows and columns for users who need to view more data at once. - **Material Theme Density 42px**: Increases spacing for easier reading, useful for users with visual impairments. --- # RTL (Right-to-Left) Support Source: https://rv-grid.com/guide/rtl RevoGrid provides comprehensive support for Right-to-Left (RTL) languages and layouts, making it suitable for applications targeting Arabic, Hebrew, Persian, and other RTL language users. The RTL support is implemented through a dedicated plugin that automatically handles column ordering, text alignment, and layout adjustments. ## Overview RTL support in RevoGrid includes: - **Automatic column reordering**: Columns are automatically reversed when RTL mode is enabled - **Text alignment**: Cell content is properly aligned for RTL languages - **Layout adjustments**: Scrollbars, headers, and interactive elements are positioned correctly - **Plugin-based architecture**: RTL functionality is implemented as a plugin for easy integration ## Basic Usage ### Enabling RTL Mode To enable RTL support, simply set the `rtl` property to `true` on your RevoGrid component: ```html ``` ### JavaScript Example ```typescript // Basic RTL setup const grid = document.querySelector('revo-grid'); grid.rtl = true; // Configure columns and data grid.columns = [ { prop: 'name', name: 'الاسم' }, { prop: 'age', name: 'العمر' }, { prop: 'city', name: 'المدينة' } ]; grid.source = [ { name: 'أحمد', age: 25, city: 'القاهرة' }, { name: 'فاطمة', age: 30, city: 'الإسكندرية' }, { name: 'محمد', age: 28, city: 'الجيزة' } ]; ``` ### Framework Examples #### Vue 3 ```vue ``` #### React ```tsx import { useState } from 'react'; function RTLGrid() { const [isRTLEnabled, setIsRTLEnabled] = useState(true); return ( ); } ``` ## Advanced Configuration ### Dynamic RTL Toggle You can dynamically toggle RTL mode based on user preferences or application state: ```typescript // Toggle RTL mode function toggleRTL() { const grid = document.querySelector('revo-grid'); grid.rtl = !grid.rtl; } // Listen for RTL state changes grid.addEventListener('rtlstatechanged', (event) => { console.log('RTL state changed:', event.detail.rtl); }); ``` ## Styling Considerations ### Custom RTL Styles RevoGrid automatically applies RTL-specific styles when the `rtl` attribute is present. You can also add custom RTL styles: ```css /* Custom RTL styles */ revo-grid[rtl] { /* Custom RTL-specific styles */ font-family: 'Arial', sans-serif; } revo-grid[rtl] .rgCell { /* Custom cell styles for RTL */ text-align: right; direction: rtl; } ``` ### RTL with Custom Cell Renderers When using custom cell renderers, ensure they respect RTL layout: ```typescript const columns = [ { prop: 'name', name: 'الاسم', cellTemplate: (h, props) => { return h('div', { style: { textAlign: props.model.rtl ? 'right' : 'left', direction: props.model.rtl ? 'rtl' : 'ltr' } }, props.model[props.prop]); } } ]; ``` ## Best Practices ### 1. Consistent RTL Implementation - Always test your application in both LTR and RTL modes - Ensure all text content is properly translated for RTL languages - Consider cultural differences in data presentation ### 2. Performance Considerations - RTL transformation is handled efficiently by the plugin system - Column reordering is performed only when necessary - No performance impact when RTL is disabled ### 3. Accessibility - Ensure proper ARIA attributes for RTL content - Test with screen readers that support RTL languages - Consider keyboard navigation patterns for RTL users ### 4. Data Formatting - Use appropriate number and date formatting for RTL locales - Consider currency symbol positioning for RTL languages - Ensure proper text direction for mixed content ## Troubleshooting ### Common Issues 1. **Columns not reordering**: Ensure the RTL plugin is properly loaded 2. **Text alignment issues**: Check if custom CSS is overriding RTL styles 3. **Performance problems**: Verify that RTL mode is only enabled when needed ### Debug Mode Enable debug mode to troubleshoot RTL issues: ```typescript // Enable debug mode const grid = document.querySelector('revo-grid'); grid.debug = true; // Check RTL state console.log('RTL enabled:', grid.rtl); ``` ### Events The RTL plugin emits events when the RTL state changes: ```typescript // Listen for RTL state changes grid.addEventListener('rtlstatechanged', (event) => { const { rtl } = event.detail; console.log('RTL state changed to:', rtl); }); ``` This comprehensive RTL support ensures that RevoGrid works seamlessly with RTL languages and provides a native experience for users in RTL locales. --- # RevoGrid Editing Source: https://rv-grid.com/guide/editing Description: Configure inline editing in RevoGrid, control read-only behavior, open editors programmatically, and handle edit lifecycle events safely. RevoGrid supports spreadsheet-style editing out of the box. You can make the whole grid editable, lock specific columns, register custom editors, and intercept writes before they are committed. ## How editing works Editing in RevoGrid is controlled by a few core pieces: - `readonly` can lock the whole grid or specific columns - `editors` registers custom editor implementations - `applyOnClose` controls whether closing an editor saves the current value - lifecycle events such as `beforeedit`, `beforeeditstart`, and `afteredit` let you validate or sync changes For source-owned synchronization without edit event handlers, see [Proxy Source Editing](https://rv-grid.com/guide/proxy-source). That pattern passes proxied row models to `source` so RevoGrid writes route through your application store. ## Minimal editable setup ```javascript const grid = document.querySelector('revo-grid'); grid.columns = [ { prop: 'id', name: 'ID', readonly: true }, { prop: 'name', name: 'Name' }, { prop: 'price', name: 'Price' }, ]; grid.source = [ { id: 1, name: 'Apple', price: 1.2 }, { id: 2, name: 'Banana', price: 0.5 }, ]; ``` By default, columns without `readonly: true` can be edited. If the grid itself has `readonly = true`, that top-level flag wins and editing is disabled across all columns. ## Read-only modes ### Lock the whole grid ```javascript const grid = document.querySelector('revo-grid'); grid.readonly = true; ``` ### Lock individual columns ```javascript grid.columns = [ { prop: 'id', name: 'ID', readonly: true }, { prop: 'name', name: 'Name' }, { prop: 'price', name: 'Price', readonly: true }, ]; ``` ### Dynamic read-only rules `readonly` can also be a function in a column type, which is useful when editability depends on row data. Example: ```ts grid.columnTypes = { editableWhenDraft: { readonly({ model }) { return model.status !== 'draft'; }, }, }; ``` ## Save control with `applyOnClose` Set `applyOnClose` when you want editor closing to commit the current value except for `Escape`-style cancellations: ```ts grid.applyOnClose = true; ``` This is useful when building custom editors with blur or close interactions. Typical use case: - click into a cell - change the value - click outside the editor - save automatically unless the user explicitly canceled ## Programmatically open an editor Use `setCellEdit` when your UI needs to move users directly into edit mode: ```ts await grid.setCellEdit(0, 'price'); ``` Arguments: - first argument: row index in the selected row viewport - second argument: column `prop` - optional third argument: row source type such as `rgRow`, `rowPinStart`, or `rowPinEnd` Read more in [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control). ## Editing lifecycle events These are the most important hooks for application logic: - `beforeeditstart`: runs before the editor opens - `beforeedit`: runs before data is committed; can cancel or rewrite the value - `beforerangeedit`: same idea for range updates - `afteredit`: runs after the edit or range change has been applied Example: ```javascript grid.addEventListener('beforeedit', event => { const { model, prop, val } = event.detail; if (prop === 'price' && Number(val) < 0) { event.preventDefault(); return; } if (prop === 'name') { event.detail.val = String(val).trim(); } }); grid.addEventListener('afteredit', event => { console.log('Edit applied', event.detail); }); ``` If you need to normalize values, `beforeedit` is the safest place to do it. Example: ```ts grid.addEventListener('beforeedit', event => { if (event.detail.prop === 'email') { event.detail.val = String(event.detail.val).toLowerCase(); } }); ``` ## Editing and focus Editing and focus are closely connected in RevoGrid: - `canFocus` controls whether focus is rendered - `setCellsFocus` can move focus before opening an editor - `clearFocus` removes the active focus state - `getSelectedRange` helps when edits depend on the current selection If you are building custom keyboard or toolbar workflows, combine the public methods instead of trying to target internal DOM elements directly. Example toolbar flow: ```ts await grid.setCellsFocus({ x: 1, y: 2 }, { x: 1, y: 2 }); await grid.setCellEdit(2, 'name'); ``` ## Common editing scenarios ### Prevent invalid numbers ```ts grid.addEventListener('beforeedit', event => { if (event.detail.prop === 'price' && Number(event.detail.val) < 0) { event.preventDefault(); } }); ``` ### Save on confirmed change ```ts grid.addEventListener('afteredit', async event => { await saveRow(event.detail.model); }); ``` ## Related guides - [Cell Editor](https://rv-grid.com/guide/cell/editor) - [Proxy Source Editing](https://rv-grid.com/guide/proxy-source) - [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control) - [Event Patterns and Lifecycles](https://rv-grid.com/guide/events-guide) - [API: RevoGrid](https://rv-grid.com/guide/api/revoGrid) ## Related Pro features If you need richer editing workflows, RevoGrid Pro adds editors and validation patterns such as row editors, checkbox editors, timeline editors, dropdown editors, and validation helpers. Start from [RevoGrid Pro](https://rv-grid.com/pro/). --- # Data Grid Export Source: https://rv-grid.com/guide/export.plugin Description: Export data from RevoGrid to CSV in the core package, use RevoGrid Pro for richer Excel export workflows, or add the PDF export package for browser-side PDF output. # Export Data from your Data Grid to file With our data grid you can export your data to file. There are three common ways to export data: - [Export to CSV file](#Export-to-CSV-file) - [Export to Excel file with RevoGrid Pro](https://rv-grid.com/guide/data-grid-export-excel) - [Export to PDF file](https://rv-grid.com/guide/pdf-export) ## Export to CSV file To export data to CSV file you need to use `exporting` option. - Setup `exporting` option on `revo-grid` to `true`: ``` tsx ``` - Access export plugin from plugin list: ``` js const grid = document.querySelector('revo-grid'); grid.getPlugins().then(plugins => { plugins.forEach(p => { if (p.exportFile) { const exportPlugin = p; exportPlugin.exportFile({ filename: 'new file' }); } }) }); ``` ## Public methods There are next methods available in export plugin and `options` object as `FormatterOptions`: - `exportFile(options)` - download file; - `exportBlob(options)` - export Blob object; - `exportString(options)` - get data string. ## Options General options are available for export: ```ts type FormatterOptions = { mime: string; // text/csv encoding: string; fileKind: string; // csv bom: boolean; columnDelimiter: string; // ',' rowDelimiter: string; // '\r\n' filename?: string; } ``` :::tip For the latest information it's recommended to read [export-plugin](https://github.com/revolist/revogrid/blob/master/src/plugins/export/export.plugin.ts) file for better understanding of parameters and options. ::: ## Related Pro features Need richer spreadsheet export workflows? [RevoGrid Pro Excel export](https://rv-grid.com/guide/data-grid-export-excel) creates workbook files that can preserve the visible grid layout, including column order, hidden columns, frozen panes, styles, merged cells, and formulas. Start with [RevoGrid Pro](https://rv-grid.com/pro/) or compare plans on [Feature Comparison](https://rv-grid.com/pro/feature-table). ## Related PDF export package Need a lightweight browser-side PDF export button? Use [`@revolist/revogrid-pdf-export`](https://www.npmjs.com/package/@revolist/revogrid-pdf-export), a RevoGrid plugin powered by [pdfmake](https://pdfmake.github.io/docs/). It exports visible rows and columns into a simple PDF table and supports grouped column headers. See [PDF Export](https://rv-grid.com/guide/pdf-export). --- # RevoGrid PDF Export Source: https://rv-grid.com/guide/pdf-export Description: Export visible RevoGrid rows and columns to PDF with the lightweight @revolist/revogrid-pdf-export plugin powered by pdfmake. Export [RevoGrid](https://rv-grid.com/) data to clean, shareable PDF files with a small browser-side plugin powered by [pdfmake](https://pdfmake.github.io/docs/). [`@revolist/revogrid-pdf-export`](https://www.npmjs.com/package/@revolist/revogrid-pdf-export) is a lightweight add-on package for teams that need a practical PDF export button without building a full reporting pipeline. It reads visible RevoGrid data, preserves column headers, respects trimmed or filtered rows, and creates a simple [pdfmake document definition](https://pdfmake.github.io/docs/0.1/document-definition-object/) that can be downloaded, previewed, uploaded, or customized. ::: tip Add-on package PDF export is delivered as a separate package. Core RevoGrid includes CSV export through the built-in export plugin. Excel-focused export workflows are available in RevoGrid Pro. ::: ## Why use it - Lightweight client-side PDF export for RevoGrid. - Works through the standard [RevoGrid plugin API](https://rv-grid.com/guide/plugin/). - Exports visible rows and visible columns. - Supports grouped column headers. - Lets you download a PDF, return a browser [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob), or access the pdfmake document definition. - Provides a cancelable `beforepdfexport` hook for customization. - Keeps the first version focused: fast to adopt, easy to reason about, and simple to extend. ## Install ```sh npm install @revolist/revogrid-pdf-export ``` The package expects RevoGrid to be present in your app. Install RevoGrid separately if your project does not already use it: ```sh npm install @revolist/revogrid ``` ## Quick start Register `ExportPdfPlugin` in the grid plugin list, then retrieve the plugin instance with `getPlugins()`. ```ts import { ExportPdfPlugin } from '@revolist/revogrid-pdf-export'; const grid = document.querySelector('revo-grid'); if (grid) { grid.plugins = [ExportPdfPlugin]; const plugins = await grid.getPlugins(); const pdf = plugins.find(plugin => plugin instanceof ExportPdfPlugin); await pdf?.exportPdf({ filename: 'orders.pdf', title: 'Orders', }); } ``` ## API ### `exportPdf(options?)` Creates and downloads a PDF file. ```ts await pdf.exportPdf({ filename: 'orders.pdf', title: 'Orders Report', }); ``` ### `exportBlob(options?)` Creates a PDF and returns it as a browser `Blob`. Use this when you want to upload, preview, store, or handle the file yourself. ```ts const blob = await pdf.exportBlob({ title: 'Orders Report', }); ``` ### `getDocumentDefinition(options?)` Returns the [pdfmake document definition](https://pdfmake.github.io/docs/0.1/document-definition-object/) before a PDF is created. Use this when you want full control over the final pdfmake rendering step. ```ts const definition = await pdf.getDocumentDefinition({ pageOrientation: 'portrait', }); ``` ## Options | Option | Type | Default | Description | | --- | --- | --- | --- | | `filename` | `string` | `revogrid-export.pdf` | Download filename. `.pdf` is added automatically when omitted. | | `title` | `string` | `RevoGrid Export` | Title shown above the exported table. | | `pageOrientation` | `'portrait' \| 'landscape'` | `landscape` | PDF page orientation. | | `includeColumnHeaders` | `boolean` | `true` | Includes the column header row. | | `includeGroupHeaders` | `boolean` | `true` | Includes grouped column header rows when present. | | `maxRows` | `number` | unlimited | Limits exported data rows. | | `tableLayout` | `string` | `lightHorizontalLines` | [pdfmake table layout](https://pdfmake.github.io/docs/0.1/document-definition-object/tables/) name. | ## Customize the PDF The plugin emits a cancelable `beforepdfexport` event with `{ data, documentDefinition, options }`. Use it to adjust the pdfmake document definition, add metadata, change styles, add headers or footers, or stop the export. ```ts grid.addEventListener('beforepdfexport', event => { event.detail.documentDefinition.info = { title: 'Orders Report', subject: 'Monthly order export', }; event.detail.documentDefinition.footer = currentPage => ({ text: `Page ${currentPage}`, alignment: 'center', fontSize: 8, }); }); ``` Call `event.preventDefault()` to cancel the export. ## What gets exported The plugin focuses on data, not pixel-perfect rendering. It exports: - visible row data - visible columns - column names - grouped column headers - filtered or trimmed grid state through RevoGrid's visible source APIs It does not attempt to reproduce custom cell renderers, DOM styling, images, row headers, pinned layout visuals, or editor UI. This keeps the PDF output small and predictable. ## Framework usage The plugin is framework-agnostic. Use it anywhere you can pass RevoGrid plugins: - [Vanilla JavaScript / TypeScript](https://rv-grid.com/guide/ts/) - [React](https://rv-grid.com/guide/react/) - [Vue 3](https://rv-grid.com/guide/vue3/) - [Angular](https://rv-grid.com/guide/angular/) - [Svelte](https://rv-grid.com/guide/svelte/) ## When to use each export option | Requirement | Recommended option | | --- | --- | | Simple CSV data export | [Core CSV export](https://rv-grid.com/guide/export.plugin) | | Browser-side PDF table export | `@revolist/revogrid-pdf-export` | | Excel workbook export/import | [RevoGrid Pro Excel export](https://rv-grid.com/guide/data-grid-export-excel) | | Fully custom report layout | Use `getDocumentDefinition()` and customize pdfmake output | ## Links - [npm package](https://www.npmjs.com/package/@revolist/revogrid-pdf-export) - [GitHub repository](https://github.com/revolist/revogrid-pdf-export) - [pdfmake documentation](https://pdfmake.github.io/docs/) - [RevoGrid plugin guide](https://rv-grid.com/guide/plugin/) - [Core CSV export](https://rv-grid.com/guide/export.plugin) - [RevoGrid Pro Excel export](https://rv-grid.com/guide/data-grid-export-excel) --- # Export Excel Source: https://rv-grid.com/guide/data-grid-export-excel Description: Export RevoGrid Pro data to Excel workbooks with visible grid layout, styles, frozen panes, merged cells, formulas, and workbook options. Export production grid views to Excel with [RevoGrid Pro](https://rv-grid.com/pro/). The Pro Excel export is built for teams that need more than a raw data dump: it creates workbook files that keep the structure and feel of the grid your users already work with. Use Excel export when a report needs to leave the browser and still feel like the original table - column order, visible columns, frozen panes, styling, merged cells, and formulas can travel with the exported workbook. ::: tip Pro feature Excel export and import are part of [RevoGrid Pro](https://rv-grid.com/pro/). Core RevoGrid includes [CSV export](https://rv-grid.com/guide/export.plugin), and browser-side PDF export is available through the [`@revolist/revogrid-pdf-export`](https://rv-grid.com/guide/pdf-export) add-on. ::: ## Why Use Pro Excel Export - Export `.xlsx` workbooks directly from the grid experience. - Preserve the visible grid layout so exported files match what users see. - Keep column order and hidden column state in the workbook output. - Carry pinned or frozen layout into Excel frozen panes. - Export styled cells for report-ready workbooks. - Support merged cells and spanned report layouts. - Keep formula-driven data useful outside the application. - Use workbook options for file name, sheet name, compression, and format. - Pair export with Pro import workflows for spreadsheet round trips. ## What Gets Preserved RevoGrid Pro Excel export is designed around the rendered grid state, not only the original source array. | Grid capability | Excel export behavior | | --- | --- | | Column order | Exports columns in the current visible order. | | Column visibility | Hidden columns stay out of the exported view. | | Frozen columns and rows | Maps pinned grid regions to Excel-style frozen panes where supported. | | Cell styles | Preserves table styling and formatting for a closer visual match. | | Grouped headers | Keeps structured header layout useful in the workbook. | | Merged cells | Exports merged and spanned regions from Pro merge workflows. | | Formulas | Works with the Pro formula pipeline so calculated sheets remain useful after export. | For the related grid features, see [Column Pinning](https://rv-grid.com/guide/column/pin), [Row Pinning](https://rv-grid.com/guide/row/pin), [Cell Merge](https://rv-grid.com/guide/cell/merge), and [Excel Formulas](https://rv-grid.com/guide/cell/formula). ## Quick Example The exact plugin registration depends on your Pro package setup, but the export flow is intentionally small: enable the Pro Excel export plugin, then send an export configuration with workbook and sheet options. ```ts const exportConfig: ExportExcelEvent = { sheetName: 'Property Data', workbookName: 'Properties.xlsx', writingOptions: { type: 'file', bookType: 'xlsx', compression: true, }, }; ``` Use your Pro setup to pass this configuration to `ExportExcelPlugin`. The plugin handles workbook creation from the current grid state. ## Workbook Formats The Pro Excel export workflow targets common spreadsheet formats used by Excel-compatible tools. The Pro feature catalog includes `xlsx`, `xlsm`, `xlsb`, `xls`, and related workbook formats. | Option | Use case | | --- | --- | | `xlsx` | Default modern Excel workbook format. | | `xlsm` | Macro-enabled workbook workflows. | | `xlsb` | Binary workbook workflows where supported. | | `xls` | Legacy Excel compatibility. | Implementation dependencies are versioned with RevoGrid Pro. See the [RevoGrid Pro third-party policy](https://rv-grid.com/pro/policies/3rdparty) for writer package and licensing notes. ## Writing Options `writingOptions` controls how the workbook is generated. Individual writer options can vary by Pro version, so use the TypeScript types shipped with your installed Pro package as the final source of truth. | Option | Description | | --- | --- | | `type` | Output mode used by the workbook writer. | | `bookType` | Workbook format such as `xlsx`, `xlsm`, `xlsb`, or `xls`. | | `compression` | Enables compression for supported workbook formats. | | `ignoreEC` | Suppresses compatible spreadsheet warnings such as number-stored-as-text checks when supported. | ```ts const exportConfig: ExportExcelEvent = { sheetName: 'Q4 Revenue', workbookName: 'q4-revenue.xlsx', writingOptions: { type: 'file', bookType: 'xlsx', compression: true, ignoreEC: true, }, }; ``` ## Best Use Cases Excel export is strongest when users expect the exported file to become a working spreadsheet, not just an archive. - Financial models with formulas and pinned summary regions. - Operations dashboards where teams sort, filter, and share workbook snapshots. - Reporting tables with merged headers, grouped columns, and styled totals. - Compliance workflows that need offline Excel files for review. - Internal tools where users already rely on Excel for analysis and handoff. ## Choosing An Export Path | Requirement | Recommended option | | --- | --- | | Raw data download | [Core CSV export](https://rv-grid.com/guide/export.plugin) | | Excel workbook with layout, styles, formulas, merge, and freeze support | [RevoGrid Pro Excel export](https://rv-grid.com/pro/) | | Shareable table PDF from the browser | [PDF export add-on](https://rv-grid.com/guide/pdf-export) | | Advanced spreadsheet-like editing before export | [RevoGrid Pro spreadsheet features](https://rv-grid.com/pro/) | ## Related Pro Features - [RevoGrid Pro](https://rv-grid.com/pro/) - [Pro feature comparison](https://rv-grid.com/pro/feature-table) - [Excel Formulas](https://rv-grid.com/guide/cell/formula) - [Cell Merge](https://rv-grid.com/guide/cell/merge) - [Column Pinning](https://rv-grid.com/guide/column/pin) - [Row Pinning](https://rv-grid.com/guide/row/pin) - [Pro third-party tools and libraries](https://rv-grid.com/pro/policies/3rdparty) --- # RevoGrid Filtering Source: https://rv-grid.com/guide/filters Description: Enable built-in filtering in RevoGrid, configure per-column filter types, preserve filter state, customize filter logic, and upgrade to RevoGrid Pro advanced filtering. Filtering lets users narrow the visible rows without changing the original `source`. RevoGrid keeps the full dataset available and hides non-matching physical row indexes through the trimming pipeline, so filtering works together with virtual scrolling, sorting, editing, and `getVisibleSource()`. ## Performance by design RevoGrid filters the data model, not the rendered DOM. It keeps the original `source` intact, calculates which rows should be visible, and lets row virtualization render only the small portion currently in the viewport. This makes filtering suitable for large, interactive datasets without creating a DOM element for every matching row. Large local filter operations automatically run in short batches so the browser can stay responsive between slices of work. When an active filter is reapplied after replacing `source`, RevoGrid keeps the new rows hidden until the result is ready, then publishes the filtered view once. Users see an empty pending view followed by the correct result—not a flash of the complete unfiltered dataset. - Small datasets keep the immediate synchronous path. - Large datasets use a responsive, cancellable path, so a newer filter or source can replace stale work. - Filtering composes with sorting, grouping, tree visibility, and other row trims before rows become visible. Client-side filtering still evaluates the local records and any active conditions. Keep custom filter functions lightweight; for datasets that should not live entirely in the browser, use [server-side filtering](https://rv-grid.com/guide/server-side-data#remote-filtering). See [Performance and Virtualization](https://rv-grid.com/guide/performance) for broader large-data guidance. ## Enable filtering Turn on the built-in filter plugin with the grid-level `filter` prop: ```ts const grid = document.querySelector('revo-grid'); grid.source = [ { name: 'Steve', role: 'Admin', score: 92 }, { name: 'Anna', role: 'Editor', score: 76 }, { name: 'John', role: 'Viewer', score: 61 }, ]; grid.columns = [ { prop: 'name', name: 'Name' }, { prop: 'role', name: 'Role' }, { prop: 'score', name: 'Score', filter: 'number' }, ]; grid.filter = true; ``` The grid-level `filter` value enables the plugin. The column-level `filter` value decides whether a column has a filter button and which filter family the panel should use. [RevoGrid filter prop](https://rv-grid.com/guide/types/JSX.Interface.RevoGrid#properties) [Column filter option](https://rv-grid.com/guide/types/Interface.ColumnRegular#properties) ## Column filter options Use `filter` on a column when you need to override the default behavior. ```ts const columns = [ { prop: 'name', name: 'Name' }, { prop: 'internalId', name: 'Internal ID', filter: false }, { prop: 'score', name: 'Score', filter: 'number' }, { prop: 'status', name: 'Status', filter: ['string', 'selection'] }, { prop: 'reference', name: 'Reference', filter: { type: 'string', default: 'eq' }, }, { prop: 'notes', name: 'Notes', filter: { type: 'string', default: false }, }, ]; ``` | Value | Use it for | | --- | --- | | `true` | Enable the default filter family for the column. | | `false` | Hide the filter UI for the column. | | `'string'` | Text matching such as contains, starts with, and equals. | | `'number'` | Numeric comparisons such as greater than and less than. | | `string[]` | Multiple filter families, often used by Pro or custom filters. | | `{ type, default }` | Select one or more filter families and optionally override the initial operator, or set `default: false` to open this column's panel empty. | ## Default filter conditions When a column has no saved or active conditions, opening its filter panel shows one removable draft condition. String columns start with **Contains** and number columns start with **=**. Boolean, array, and custom filter families use their first available operator. The draft is ready for input but is not an applied filter. Opening or closing the panel does not filter rows, activate the header filter icon, emit filtering events, or add the draft to persisted filter state. Entering a value or explicitly selecting an operator promotes it to a normal condition. If dynamic filtering is disabled, the promoted condition remains local until **Save**. Use the structured column form to choose a different initial operator: ```ts grid.columns = [ { prop: 'name', name: 'Name', filter: { type: 'string', default: 'eq' }, }, { prop: 'score', name: 'Score', filter: { type: ['number', 'string'], default: 'gte' }, }, ]; ``` To keep the original empty-panel behavior everywhere, disable default drafts in the grid filter configuration. A column can opt out independently with `default: false`. Conversely, an explicit operator on a column opts that column back in when the grid-wide setting is disabled. ```ts grid.filter = { defaultFilter: false }; grid.columns = [ { prop: 'name', filter: 'string' }, // Opens empty. { prop: 'notes', filter: { type: 'string', default: false } }, // Opens empty. { prop: 'status', filter: { type: 'string', default: 'eq' } }, // Opens with Equal. ]; ``` The override must name an operator available to one of the configured families. It is resolved after `include` and custom filters are applied. If it is invalid or excluded, RevoGrid uses the built-in family default when available, then the first available operator from the first configured family. Removing the draft or clicking **Reset** leaves the current panel empty. A new draft is created the next time that column's panel is opened. Existing filters loaded through `collection`, `multiFilterItems`, or the `filter` event are shown as-is and never receive an extra draft. ## Built-in filter operations String columns support `notEmpty`, `empty`, `eq`, `notEq`, `begins`, `contains`, and `notContains`. Number columns support `notEmpty`, `empty`, `eqN`, `neqN`, `gt`, `gte`, `lt`, and `lte`. Boolean and array columns support the blank operations `notEmpty` and `empty`. In the filter panel, `empty` is labeled **Is blank** and `notEmpty` is labeled **Is not blank**. The operation ids have not changed, so existing saved filter state remains compatible. These ids are also the values used by `include`, localization, and event payloads. [FilterItem](https://rv-grid.com/guide/types/Interface.FilterItem) [FilterType](https://rv-grid.com/guide/types/TypeAlias.FilterType) ## Configure `ColumnFilterConfig` Pass an object to `grid.filter` when you need controlled behavior instead of the default plugin setup. ```ts grid.filter = { defaultFilter: false, include: ['contains', 'eq', 'notEmpty', 'gt', 'gte', 'lt', 'lte'], disableDynamicFiltering: true, closeFilterPanelOnOutsideClick: false, allowDuplicateOperators: false, }; ``` Important options: | Option | Purpose | | --- | --- | | `blankSemantics` | Defines which source values the blank operators match across the grid. | | `defaultFilter` | Controls whether empty panels start with a draft condition. Defaults to `true`. | | `collection` | Restores single-filter state by column prop. | | `multiFilterItems` | Restores multiple filters per column, including `and` / `or` relations. | | `include` | Limits the operations shown in the dropdown. | | `customFilters` | Registers custom operations. | | `filterProp` | Uses a custom column property instead of `filter` to decide whether a column is filterable. | | `localization` | Replaces filter captions and operation names. | | `disableDynamicFiltering` | Applies changes only when the user confirms. | | `closeFilterPanelOnOutsideClick` | Controls whether outside clicks close the filter panel. | | `allowDuplicateOperators` | Allows the same operator to be selected more than once per column. Defaults to `true`; set to `false` to make visible operators mutually exclusive in the panel. | When `allowDuplicateOperators` is `false`, the filter panel hides operators already used by the current column from the **Add condition** dropdown. Existing conditions remain editable, and programmatically supplied duplicate `multiFilterItems` are preserved. [ColumnFilterConfig](https://rv-grid.com/guide/types/Interface.ColumnFilterConfig) [FilterCollectionItem](https://rv-grid.com/guide/types/TypeAlias.FilterCollectionItem) [MultiFilterItem](https://rv-grid.com/guide/types/Interface.MultiFilterItem) ## Configure blank values The **Is blank** and **Is not blank** operations preserve the original source value instead of converting all falsy values to the same representation. The default policy is: | Source value | Blank by default | | --- | --- | | `null` | Yes | | An own property whose value is `undefined` | Yes | | An empty string (`''`) | Yes | | A missing own property | Yes | | A whitespace-only string such as `' '` | No | | An empty array (`[]`) | No | | `false`, `0`, or `NaN` | No | | Non-empty arrays and objects | No | Set `blankSemantics` on the grid filter config to change this policy. Every field is optional: ```ts grid.filter = { blankSemantics: { whitespaceOnlyString: true, emptyArray: true, null: true, undefined: true, emptyString: true, missingProperty: true, }, }; ``` A column can override individual fields without repeating the grid policy. Column settings are merged field-by-field over the grid settings and the defaults: ```ts grid.columns = [ { prop: 'tags', name: 'Tags', filter: 'array', // Keep [] as a non-blank value for this column only. blankSemantics: { emptyArray: false }, }, { prop: 'active', name: 'Active', filter: 'boolean', }, ]; ``` Use `isBlank` for application-specific values. It runs after the configured rules and receives their result as `fallbackResult`: ```ts grid.filter = { blankSemantics: { isBlank(value, context, fallbackResult) { if (context.property === 'status' && value === 'N/A') { return true; } return fallbackResult; }, }, }; ``` The callback receives the unparsed source `value` plus a context containing `model`, `column`, `property`, `sourceValue`, `parsedValue`, `hasOwnProperty`, and the effective `blankSemantics`. Inherited properties count as missing because `hasOwnProperty` is `false`. Blank checks always use `sourceValue`, even when the column has a `cellParser`. Other built-in and custom filter operations continue to receive `parsedValue`. Configuring blank semantics does not coerce values for typed comparisons, so number, string, boolean, and array operators keep their existing strict behavior. **Is not blank** is the exact inverse of the resolved blank predicate, including the result returned by `isBlank`. ## Customize filter names Use `localization.filterNames` to replace the labels shown for built-in filter operations. For example, you can use shorter labels for the default **Is blank** and **Is not blank** operations: ```ts import { filterNames } from '@revolist/revogrid'; grid.filter = { localization: { captions: {}, filterNames: { ...filterNames, empty: 'Blank', notEmpty: 'Not blank', }, }, }; ``` Spreading `filterNames` keeps all other built-in labels unchanged and satisfies the complete `FilterLocalization` mapping expected by TypeScript. Override any other operation id in the same object, such as `eq` for **Equal** or `contains` for **Contains**. The ids remain `empty` and `notEmpty` for compatibility with saved filters, regardless of the labels you display. [FilterLocalization](https://rv-grid.com/guide/types/Interface.FilterLocalization) ## Restore saved filters Use `collection` for simple saved filters: ```ts grid.filter = { collection: { role: { type: 'eq', value: 'Admin' }, score: { type: 'gte', value: 80 }, }, }; ``` Use `multiFilterItems` when a column needs several conditions: ```ts grid.filter = { multiFilterItems: { score: [ { id: 1, type: 'gte', value: 70 }, { id: 2, type: 'lt', value: 95, relation: 'and' }, ], role: [ { id: 3, type: 'eq', value: 'Admin' }, { id: 4, type: 'eq', value: 'Editor', relation: 'or' }, ], }, }; ``` ## Filter parsed values If a cell displays formatted text but filtering should use normalized data, add `cellParser` to the column or column type. ```ts const columns = [ { prop: 'total', name: 'Total', filter: 'number', cellTemplate: (h, { model, prop }) => h('span', `$${Number(model[prop]).toLocaleString()}`), cellParser: (model, column) => Number(model[column.prop] ?? 0), }, ]; ``` See [Column Types and Formats](https://rv-grid.com/guide/column/types) and [Custom Cell Formats](https://rv-grid.com/guide/cell/custom-formats) for reusable parser patterns. ## Create a custom filter Register custom operations through `customFilters`. The `columnFilterType` must match the column's `filter` value. ```ts const matchesPriority = (value, expected = 'critical') => String(value).toLowerCase() === String(expected).toLowerCase(); matchesPriority.extra = 'input'; grid.columns = [ { prop: 'ticket', name: 'Ticket' }, { prop: 'priority', name: 'Priority', filter: 'ticketPriority' }, ]; grid.filter = { include: ['isHighPriority'], customFilters: { isHighPriority: { columnFilterType: 'ticketPriority', name: 'High priority', func: matchesPriority, }, }, }; ``` The filter function receives the parsed cell value and the extra value from the filter panel. `func.extra = 'input'` asks the panel to render an input for that operation. The filter API also supports `datepicker` or a custom extra-field renderer for specialized UIs. [CustomFilter](https://rv-grid.com/guide/types/Interface.CustomFilter) ### Choose the right extension point Filtering can be extended at several levels without replacing the whole plugin: - Use `cellParser` to normalize a stored value before built-in or custom operations evaluate it. - Use `customFilters` to add a reusable operation that returns `true` or `false` for each row. - Use `beforefilterapply` to inspect, rewrite, or delegate the requested filter before evaluation starts. - Use `beforefiltertrimmed` when your application needs final control over the physical row indexes that will be hidden. Custom filter functions are synchronous predicates. RevoGrid may call them once per row for each active condition, so keep them pure and fast: avoid network requests, DOM work, large allocations, and shared-state mutations. Do not declare a custom predicate `async` or return a `Promise`; a promise is not a deferred boolean filter result. ### How asynchronous filtering works For large local datasets, RevoGrid can yield between batches of synchronous predicate calls. The overall operation can continue across browser tasks while every individual custom predicate remains simple and synchronous. If a newer filter or source arrives, stale batched work can be discarded before it changes the visible result. When filtering genuinely requires asynchronous work—such as an API request, database query, or permission service—prevent the local operation in `beforefilterapply` and let your data controller load the matching rows into `source`. The controller should cancel or ignore stale requests and guard against requesting the same filter again when the remote source is assigned. See [Remote filtering](https://rv-grid.com/guide/server-side-data#remote-filtering) for the recommended flow. ## Event hooks Filtering is event-driven. Use these hooks when your app needs to observe, rewrite, or replace filtering behavior. ```ts grid.addEventListener('beforefilterapply', event => { const { collection } = event.detail; for (const prop of Object.keys(collection)) { if (collection[prop].value === '') { delete collection[prop]; } } }); grid.addEventListener('beforefiltertrimmed', event => { console.log('Rows about to be hidden', event.detail.itemsToFilter); }); ``` Useful events: | Event | When to use it | | --- | --- | | `beforefilterapply` | Inspect or modify the filter collection before rows are evaluated. | | `beforefiltertrimmed` | Inspect or replace the physical row indexes that will be hidden. | | `beforetrimmed` | Intercept trimming generally, including filtering-driven trimming. | | `aftertrimmed` | React after visible rows have changed. | | `filterconfigchanged` | Persist new filter config when the `filter` prop changes. | For the full event table, see [API: Events](https://rv-grid.com/guide/api/events) and [API: RevoGrid](https://rv-grid.com/guide/api/revoGrid). For the filtering event flow, see [Event Patterns and Lifecycles](https://rv-grid.com/guide/events-guide#filtering). When the backend must own the filtered dataset, intercept `beforefilterapply`, prevent local trimming, and reload `source` from your server. See [Server-side data, pagination, sorting, and filtering](https://rv-grid.com/guide/server-side-data#remote-filtering). ## Read filtered rows After a filter is applied, use `getVisibleSource()` when the application needs the current visible dataset. ```ts const visibleRows = await grid.getVisibleSource(); const visibleEmails = visibleRows.map(row => row.email); ``` See [Programmatic Control](https://rv-grid.com/guide/programmatic-control#read-visible-rows). ## Pro filtering The open-source filter plugin is a strong base: text and number operations, custom functions, localization, saved state, and event hooks are all available in the Community package. RevoGrid Pro builds on the same API and makes filtering feel closer to a full spreadsheet or back-office data product. Import the Pro plugins and stylesheet, then add the plugins to the grid `plugins` list. `AdvanceFilterPlugin` adds selection, slider, quick-search, and date filter operations; `FilterHeaderPlugin` adds always-visible header inputs. ```ts import { AdvanceFilterPlugin, FilterHeaderPlugin, FIlTER_SELECTION, FIlTER_SLIDER, } from '@revolist/revogrid-pro'; import '@revolist/revogrid-pro/dist/revogrid-pro.css'; const plugins = [AdvanceFilterPlugin, FilterHeaderPlugin]; const columns = [ { prop: 'city', name: 'City', filter: ['string', FIlTER_SELECTION] }, { prop: 'status', name: 'Status', filter: [FIlTER_SELECTION] }, { prop: 'createdAt', name: 'Created', filter: ['date'] }, { prop: 'amount', name: 'Amount', filter: ['number', FIlTER_SLIDER] }, { prop: 'owner', name: 'Owner', filter: ['input'] }, ]; grid.plugins = plugins; grid.columns = columns; grid.filter = true; ``` ### Advanced Selection Filtering Selection filtering gives users a fast pick-list for repeated values such as status, city, category, owner, country, or product type. It is ideal for operational grids where users already know the value they want and should not have to type exact text into a generic input. ### Advanced Slider Filtering Slider filtering adds a range-based control for numeric columns. It works well for prices, quantities, ratings, scores, budgets, and other bounded numeric values where users want to narrow a dataset visually instead of entering `gte` and `lte` values manually. ### Header Input Filtering Header input filtering keeps filter inputs visible directly in the header row. This is useful for dense back-office screens where filtering is a constant workflow and users need to scan, type, adjust, and compare without opening a popup for every column. ### Date Filter Date filtering adds date-aware operations for temporal data such as schedules, orders, logs, audit records, deadlines, and activity history. Users can filter by exact dates, ranges, and common date windows without writing custom date parsing logic. ### Multi-Filtering Multi-filtering lets users combine several conditions per field with clearer `and` / `or` workflows. It is especially useful when a single column needs layered logic, for example "amount is greater than 100 and less than 500" or "status is open or pending". These Pro filters are valuable when users live in the grid all day: they can narrow a large dataset from several angles, combine filters without leaving the table, and keep the interaction fast because the Pro features plug into RevoGrid's existing virtualized rendering and filter events. Start with [RevoGrid Pro features](https://rv-grid.com/pro/#features), or open the business demos that use Pro workflows: - [Pivot analytics demo](https://rv-grid.com/pivot/) ## Related docs - [JavaScript filtering demo](https://rv-grid.com/guide/demos/js/js.filtering) - [Column Types and Formats](https://rv-grid.com/guide/column/types) - [Server-side data, pagination, sorting, and filtering](https://rv-grid.com/guide/server-side-data) - [Programmatic Control](https://rv-grid.com/guide/programmatic-control) - [Event Patterns and Lifecycles](https://rv-grid.com/guide/events-guide#filtering) - [API: Events](https://rv-grid.com/guide/api/events) - [API: RevoGrid](https://rv-grid.com/guide/api/revoGrid) - [API: ColumnFilterConfig](https://rv-grid.com/guide/types/Interface.ColumnFilterConfig) --- # RevoGrid Plugin System Source: https://rv-grid.com/guide/plugin Description: Learn how to build RevoGrid plugins with BasePlugin, providers, event subscriptions, dispatching, lifecycle cleanup, and extension points. # Plugin System [Interface: PluginBaseComponent](https://rv-grid.com/guide/types/Interface.PluginBaseComponent) [TypeAlias: PluginProviders](https://rv-grid.com/guide/types/TypeAlias.PluginProviders) RevoGrid offers a powerful and flexible plugin system that allows you to extend its functionality. By creating custom plugins, you can add new features, modify existing behavior, and integrate RevoGrid with other libraries or frameworks. ## Creating a Plugin All plugins in RevoGrid extend from the `BasePlugin` class, which provides a minimal starting core and utility methods for working with the RevoGrid component. ### BasePlugin Class The `BasePlugin` class serves as a foundational layer for creating plugins. Here's an overview of its interface and capabilities: ```typescript /** * Base layer for plugins * Provide minimal starting core for plugins to work * Extend this class to create plugin */ export class BasePlugin implements PluginBaseComponent { readonly subscriptions: Record void> = {}; constructor(public revogrid: HTMLRevoGridElement, public providers: PluginProviders) {} /** * Subscribe to an event in the RevoGrid component. * @param eventName - event name to subscribe to in RevoGrid component (e.g. 'beforeheaderclick') * @param callback - callback function for the event */ addEventListener(eventName: string, callback: (e: CustomEvent) => void): void; /** * Subscribe to a property change in the RevoGrid component. * You can return false in the callback to prevent the default value set. * @param prop - property name * @param callback - callback function * @param immediate - trigger callback immediately with current value */ watch( prop: string, callback: (arg: T) => boolean | void, config?: Partial ): void; /** * Remove an event listener. * @param eventName - event name */ removeEventListener(eventName: string): void; /** * Emit an event from the RevoGrid component. * The event can be cancelled by calling event.preventDefault() in the callback. * @param eventName - event name * @param detail - event detail */ emit(eventName: string, detail?: any): CustomEvent; /** * Clear all subscriptions. */ clearSubscriptions(): void; /** * Destroy the plugin and clear all subscriptions. */ destroy(): void; } ``` ### Plugin Lifecycle 1. **Initialization**: When a plugin is created, it initializes with references to the RevoGrid component and its providers. 2. **Event Subscription**: Plugins can subscribe to RevoGrid events using `addEventListener`. 3. **Property Watchers**: Plugins can watch for property changes using `watch`. 4. **Event Emission**: Plugins can emit custom events using `emit`. 5. **Cleanup**: Plugins should clean up their subscriptions using `clearSubscriptions` and `destroy` methods. ### Dispatching Events In RevoGrid, custom events are dispatched to elements using the `dispatch` and `dispatchByEvent` functions. These functions are essential for creating responsive and interactive plugins in RevoGrid, ensuring that events propagate correctly to the top level of the application. [Read more here](https://rv-grid.com/guide/types/README#dispatch-) ### Example Plugin Here's an example of a simple plugin that logs when a cell is focused: ```typescript class CellLogger extends BasePlugin { constructor(revogrid: HTMLRevoGridElement, providers: PluginProviders) { super(revogrid, providers); this.addEventListener('beforecellfocus', this.handleCellFocus); } private handleCellFocus = (e: CustomEvent) => { console.log('Cell focused:', e.detail); }; } // Usage const gridElement = document.querySelector('revo-grid'); gridElement.plugins.push(CellClickLogger); ``` ## Plugin Providers For more advanced plugins, you might need to interact with these providers directly. The `PluginProviders` type includes several providers that give access to different parts of RevoGrid's internal state: - **Data Manipulation**: Use the `data` provider to manipulate the data in the grid. - **Dimension Handling**: Use the `dimension` provider to manage row and column dimensions. - **Selection Management**: Use the `selection` provider to handle cell and row selections. - **Column Management**: Use the `column` provider to manage column data and properties. - **Viewport Management**: Use the `viewport` provider to handle scrolling and viewport rendering. ## Conclusion The RevoGrid plugin system provides a powerful way to extend and customize the grid's functionality. By leveraging the `BasePlugin` class and the provided utility methods, you can create robust plugins that enhance the capabilities of RevoGrid. If you have any questions or need further assistance, feel free to reach out to the RevoGrid community or check our [RevoGrid Pro](https://rv-grid.com/pro). --- # Security Source: https://rv-grid.com/guide/security # Security 🛡️ **RevoGrid** is a JavaScript library designed to ensure your application meets your security requirements. ## Content Security Policy (CSP) The basic information on Content Security Policy can be found on the [MDN web docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP). ## Security Vulnerability Testing [![SonarCloud](https://sonarcloud.io/images/project_badges/sonarcloud-white.svg)](https://sonarcloud.io/summary/new_code?id=revolist_revogrid) Applications using RevoGrid may need to pass security tests before production deployment. RevoGrid is tested for a variety of security vulnerabilities using the SonarQube automatic security testing tool. SonarQube evaluates security using well-established standards such as CWE, SANS Top 25, and OWASP Top 10. ### SonarQube Results The SonarQube security test results for our main NPM packages are available, ensuring that RevoGrid maintains high security standards. [![Quality gate](https://sonarcloud.io/api/project_badges/quality_gate?project=revolist_revogrid)](https://sonarcloud.io/summary/new_code?id=revolist_revogrid) --- # Server-side data, pagination, sorting, and filtering Source: https://rv-grid.com/guide/server-side-data Description: Build a production server-side data layer for RevoGrid with remote pagination, infinite loading, sorting, filtering, grouping, request cancellation, caching, and edit sync. You Data Grid can render large local datasets efficiently, but in production often cannot load the whole dataset into the browser. Your backend may own permissions, search, joins, sorting, filtering, grouping, totals, audit logs, and edit validation. This guide describes an application-owned server-side data layer around RevoGrid. It does not add a new grid API. The grid still receives rows through `source`, columns through `columns`, and user intent through events. Your app owns the remote query, cache, loading state, error state, and persistence. ::: info Use this pattern when - the complete dataset is too large for browser memory - sorting or filtering must match backend authorization rules - edits must be validated, audited, or merged by the server - users need pagination, infinite loading, or grouped remote data - stale network responses must not overwrite newer user intent ::: ## Recommended model Treat RevoGrid as the viewport and interaction layer. Treat your data controller as the source of truth for the active remote window. ```txt user action -> RevoGrid event -> app data controller -> backend request -> grid.source ``` The important boundary is that full `source` replacement means "the remote dataset window changed". Do not recreate `source` after every cell edit just to mirror local state. For edit syncing patterns, see [Data Source Loading and Syncing](https://rv-grid.com/guide/data-sync). ## Backend query Use one query shape for page loads, infinite-scroll windows, sorting, filtering, quick search, and grouping. Keep the request explicit and serializable so it can become a cache key. ```ts type SortOrder = 'asc' | 'desc'; type GridQuery = { offset: number; limit: number; sort?: Record; filter?: Record; group?: { by: string[]; route?: string[] }; search?: string; }; type GridResponse = { rows: Row[]; total?: number; hasMore?: boolean; }; ``` Use `total` when the backend can count cheaply. Use `hasMore` when counting is expensive or the dataset is streaming. For edits, use a separate mutation endpoint. Do not mix row loading and cell persistence into one route. ```ts type GridEditRequest = { rowId: string | number; field: string; value: unknown; previousValue?: unknown; }; type GridEditResponse = { accepted: boolean; row?: Row; message?: string; }; ``` The backend should return the canonical row when it normalizes values, applies business rules, or writes server-generated fields such as `updatedAt`. ## Pagination and infinite scrolling Server-side pagination uses a fixed `page` and `limit`: ```txt page 0 -> offset 0, limit 100 page 1 -> offset 100, limit 100 ``` Infinite scrolling uses the same backend contract, but the trigger comes from the scroll position instead of a page button: ```txt visible range approaches end -> request next offset -> append or replace window ``` Choose the behavior based on product needs: | Pattern | Use it when | Grid source strategy | | --- | --- | --- | | Pagination | Users need stable pages, URLs, or exports by page | Replace `source` with the requested page. | | Infinite scrolling | Users scan a long operational feed | Load windows by offset and keep enough rows for smooth scrolling. | | Pro Infinity Scroll | You want plugin-managed chunk loading and buffer cleanup | Start from [RevoGrid Pro](https://rv-grid.com/pro/). | The backend contract should be the same either way. That keeps filtering, sorting, caching, and export code reusable. ## Remote sorting For server-authoritative sorting, mark columns as sortable so users get the normal header interaction. Then intercept `beforesortingapply`, call `event.preventDefault()`, and reload from the backend. ```ts grid.columns = [ { prop: 'name', name: 'Name', sortable: true }, { prop: 'createdAt', name: 'Created', sortable: true }, ]; ``` Use the event to send `{ [column.prop]: order }` to the backend. If you support multi-sort, keep the full sort object in the controller and honor the event's `additive` flag. ## Remote filtering For server-authoritative filtering, enable the normal filter UI, intercept `beforefilterapply`, prevent local trimming, and send the collection to the backend. ```ts grid.filter = true; grid.addEventListener('beforefilterapply', event => { event.preventDefault(); void controller.setFilter(event.detail.collection); }); ``` The filter collection uses RevoGrid's column props and filter operation ids. Your API can accept this shape directly or translate it to a backend-specific query language. ## Remote grouping Client-side grouping is appropriate when the browser owns the complete dataset. Server-side grouping is different: the backend must own group keys, child routes, counts, aggregates, sorting, filtering, and lazy expansion. Use a route-based query shape: ```ts const query: GridQuery = { offset: 0, limit: 100, group: { by: ['country', 'city'], route: ['Germany'] }, sort: { revenue: 'desc' }, filter: { status: { type: 'eq', value: 'active' } }, }; ``` For production grouping with lazy expansion and route cache behavior, start from [RevoGrid Pro](https://rv-grid.com/pro/). ## Cancellation, races, and cache keys Remote grid UIs create overlapping requests. A user can type a filter, click sort, change page, and edit a row before the first response returns. Use all three safeguards: - Abort the previous request with `AbortController`. - Track a monotonically increasing request id and ignore stale responses. - Build cache keys from the complete query: `{ page, limit, sort, filter, group, search }`. Do not key the cache only by page number. Page 2 of "all rows" is not the same data as page 2 after filtering by status or sorting by date. For shared caches, normalize object key order before serializing. The example uses `JSON.stringify(query)` because it builds the query in a stable order in one place. ## Optimistic edits and backend sync RevoGrid applies cell edits before `afteredit` fires. That makes optimistic saves straightforward: 1. Let the grid apply the local edit. 2. Send `{ rowId, field, value, previousValue }` to the backend from `afteredit`. 3. If the backend accepts and returns a canonical row, merge it into the model. 4. If the backend rejects, restore the previous value with `setDataAt`. 5. Clear remote caches that may contain the old row. Use `beforeedit` when a rule can be decided locally and the edit should be blocked before it changes the model. Use `afteredit` when the server is the authority and the UI should feel responsive while the save is in flight. ## Loading and error states Keep loading and error state in the controller or app shell: - disable pagination buttons while the current page is loading - show a small overlay or status row during the first load - keep old rows visible during background refresh when possible - show retry controls for failed loads - show field-level or row-level messages for rejected edits Avoid network calls or loading state inside cell templates. Cell renderers run as part of virtual rendering and should stay cheap. See [RevoGrid Performance and Virtualization](https://rv-grid.com/guide/performance). ## Checklist - Keep `columns` stable and replace `source` only when the remote window changes. - Use `beforesortingapply` for remote sorting. - Use `beforefilterapply` for remote filtering. - Cancel in-flight requests and ignore stale responses. - Include sort, filter, group, search, offset, and limit in cache keys. - Keep loading and error UI outside cell renderers. - Use `afteredit` for optimistic save and rollback. - Let the backend own server grouping, counts, aggregates, and permissions. ## Related guides - [Data Source Loading and Syncing](https://rv-grid.com/guide/data-sync) - [RevoGrid Performance and Virtualization](https://rv-grid.com/guide/performance) - [RevoGrid Best Practices](https://rv-grid.com/guide/patterns) - [RevoGrid Filtering](https://rv-grid.com/guide/filters) - [Data Grid Sorting](https://rv-grid.com/guide/sorting) - [Event Patterns and Lifecycles](https://rv-grid.com/guide/events-guide) - [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control) --- # Slots Source: https://rv-grid.com/guide/slots # Slots RevoGrid uses slots, a feature of StencilJS, to allow you to inject custom content into specific parts of the grid. This provides flexibility for customizing the appearance and functionality of your grid. ## Available Slots ### Data Slots Data slots allow you to add extra elements to the main data area of the grid. - **Format**: `data-{column-type}-{row-type}` - **Example**: `data-rgCol-rgRow` This slot applies additional elements within the `` component, which is responsible for rendering the main data cells. ```html
Custom Content
``` ### Focus Slots Focus slots enable you to add elements to the focus layer of the grid, which is used to indicate the currently focused cell or range. - **Format**: `focus-{column-type}-{row-type}` - **Example**: `focus-rgCol-rgRow` This slot applies extra elements within the `` component, enhancing the visual representation of the focused cells. ```html
Focused Content
``` ## Examples Here are some examples of how to use these slots: ### Data Slot Example Add custom content to the main data cells: ```html
Custom Data Element
``` ### Focus Slot Example Add custom content to the focus layer: ```html
Focus Element
``` By utilizing these slots, you can extend and customize the functionality and appearance of RevoGrid to better fit your application's needs. For more details, please refer to the [API documentation](https://rv-grid.com/guide/api/revoGrid). --- # Data Grid Sorting Source: https://rv-grid.com/guide/sorting Description: Configure RevoGrid sorting with sortable columns, default sort order, custom compare functions, and sorting lifecycle events. Adding sorting to your data grid is quite straightforward: - **Add `sortable` property to the column**: Enables sorting to be triggered on header click. - **Add `order` property to the column**: Specifies the default sorting order, either `asc` (ascending) or `desc` (descending). - **(Optional) Add `cellCompare` method to the column**: Provides custom sorting logic. ### Example Here’s an example of how to add sorting to your columns: ```javascript const columns = [ { name: 'Name', prop: 'name', sortable: true, // Enables sorting order: 'asc', // Default sorting order cellCompare: (prop, a, b) => { // Custom sorting logic const av = a[prop]?.toString().toLowerCase(); const bv = b[prop]?.toString().toLowerCase(); return av - bv; } }, ]; const items = [ { name: 'John Doe', age: 30 }, { name: 'Jane Smith', age: 25 } ]; grid.columns = columns; grid.source = items; ``` ## Sorting Events :::tip For more details, please refer to the API section and the column data schema interfaces. ::: - **`beforesorting`** - `CustomEvent<{ column: ColumnRegular, order: 'desc' | 'asc' }>` - Triggered after a header click and before sorting starts. Use `e.preventDefault()` to prevent any further sorting chain. If this event is prevented, `beforesortingapply` will not be triggered. - **`beforesortingapply`** - `CustomEvent<{ column: ColumnRegular, order: 'desc' | 'asc' }>` - Triggered before the sorting data is applied. Use `e.preventDefault()` to avoid the default data sorting and implement your own sorting logic. - **`aftersortingapply`** - `CustomEvent<{ sorting?: SortingOrder, sortingColumns?: Record | undefined>, sortingOrder?: ColumnProp[], types: DimensionRows[] }>` - Triggered after sorting has been applied and completed. Use `sortingColumns` to inspect the columns that sorting was applied to and `sorting` for the applied order. For server-authoritative sorting, intercept `beforesortingapply`, call `e.preventDefault()`, and reload `source` from your backend with the requested sort state. See [Server-side data, pagination, sorting, and filtering](https://rv-grid.com/guide/server-side-data#remote-sorting). ## Lifecycle 1. **`@event` `beforesorting`** - Triggered when sorting is initiated. At this point, no changes have been made yet. This event can be triggered by sorting from a column or from the source. If the sorting type is from rows, the column will be undefined. 2. **`@method` `updateColumnSorting`** - This method updates the column sorting icon on the grid and the column itself, but the data remains unchanged. 3. **`@event` `beforesortingapply`** - Triggered before the sorting data is applied to the data source. You can prevent this event to stop the data from being sorted. This event is only called when sorting is initiated from a column click. 4. **`@event` `aftersortingapply`** - Triggered after the sorting has been applied and completed. The event detail provides the final sorting state, sorting column metadata, sorting priority, and affected row store types. --- # Single file bundle Source: https://rv-grid.com/guide/standalone # Single file bundle RevoGrid also offers a single file bundle without the polyfills and other additional functionality included in the default output. You would need additional dependency to load RevoGrid as standalone esm module. ::: code-group ```npm npm i @stencil/core ``` ```pnpm pnpm add @stencil/core ``` ```yarn yarn add @stencil/core ``` ```bun bun add @stencil/core ``` ::: Now you can import `RevoGrid` into your app: ```js import { defineCustomElement } from "@revolist/revogrid/standalone"; // A utility defineCustomElement() function is exported from esm file of the output directory. // This function can be used to quickly define all RevoGrid components in a project on the custom elements registry. defineCustomElement(); import { defineCustomElement as defineFilterPanel } from '@revolist/revogrid/standalone/revogr-filter-panel.js'; // Filter is defined as a standalone component plugin and should be imported here defineFilterPanel?.(); ``` Please note that this standalone output does not automatically define the custom elements or apply any polyfills which is why we’re defining the custom element above ourselves. For more details, please see [Stencil.js documentation](https://stenciljs.com/docs/custom-elements). ## Standalone JavaScript Data Grid Starter [![Edit RG - Start (Standalone)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-custom-sizes-per-row-forked-dq2mjk) --- # SSR (Server side rendering) Source: https://rv-grid.com/guide/ssr # SSR (Server side rendering) RevoGrid library includes a hydrate app that is a bundle of the same components, but compiled so that they can be hydrated on a NodeJS server and generate static HTML and CSS. To get started, import the hydrate app into your server’s code like so: ```js import hydrate from "@revolist/revogrid/hydrate" ``` If you are using for example [Eleventy](https://www.11ty.dev/), you could now add a transform into `.eleventy.js` configuration file that takes content as an input and processes it using RevoGrid’s hydrate app: ```js eleventyConfig.addTransform("hydrate", async(content, outputPath) => { if (process.env.ELEVENTY_ENV == "production") { if (outputPath.endsWith(".html")) { try { const results = await hydrate.renderToString(content, { clientHydrateAnnotations: true, removeScripts: false, removeUnusedStyles: false }) return results.html } catch (error) { return error } } } return content }) ``` The above transform gives you server side rendered components that function without JavaScript. Please note that you need to separately pre-render the content for each theme you want to support. --- # RevoGrid Themes Source: https://rv-grid.com/guide/theme Description: Use built-in RevoGrid themes, inheritable CSS variables, and typed per-grid custom theme definitions. # Themes RevoGrid includes five built-in themes and supports two additive customization paths: - CSS custom properties for local or application-wide styling - typed `ThemeDefinition` presets for reusable, per-grid themes Both paths use the existing `theme` property. A custom theme name stays reflected in the `theme` attribute, so ordinary CSS selectors remain available as an advanced escape hatch. ## Built-in themes | Theme | Structure | Color scheme | Default row height | | -------------- | --------- | ------------ | -----------------: | | `default` | Default | Light | 27 px | | `material` | Material | Light | 42 px | | `compact` | Compact | Light | 32 px | | `darkMaterial` | Material | Dark | 42 px | | `darkCompact` | Compact | Dark | 32 px | ```js const grid = document.querySelector('revo-grid') grid.theme = 'material' ``` Changing `theme` at runtime updates the structure, color scheme, tokens, and default density together. After application, RevoGrid emits `afterthemechanged` with the normalized theme name in `event.detail`. ## CSS-only customization CSS variables inherit normally. Define them on an application container to affect all descendant grids, or on one grid for an instance-specific override. ```css .billing-screen { --revo-grid-font-family: Inter, system-ui, sans-serif; --revo-grid-primary: #6d4aff; } revo-grid[theme='billing'] { --revo-grid-background: #fbfaff; --revo-grid-header-bg: #f0edff; --revo-grid-header-color: #241c45; --revo-grid-selection-border: #6d4aff; } ``` ```js const grid = document.querySelector('revo-grid') grid.theme = 'billing' ``` Any non-empty name is valid. If no typed definition exists, the name remains reflected and RevoGrid uses `default` layout metadata. A blank name normalizes to `default`. ## Typed reusable themes Use `defineTheme` for type checking and autocomplete. A custom theme can extend a built-in theme or another custom definition registered on the same grid. ```ts import { defineTheme, type ThemeDefinition } from '@revolist/revogrid' export const billingTheme = defineTheme({ name: 'billing', extends: 'darkMaterial', defaultRowSize: 36, tokens: { primary: '#9b8cff', background: '#17151f', text: '#f4f1ff', headerBg: '#242031', selectionBorder: '#b8adff', filterPanelBg: '#242031', filterPanelText: '#f4f1ff', }, } satisfies ThemeDefinition) const grid = document.querySelector('revo-grid')! grid.themeDefinitions = [billingTheme] grid.theme = billingTheme.name ``` `themeDefinitions` is a JavaScript property containing objects. Do not serialize it into an HTML attribute. Built-in names are reserved, and the last definition wins when the array contains duplicate custom names. Invalid or missing parents, non-positive `defaultRowSize` values, invalid color schemes, and unknown token keys are ignored in favor of default or inherited values. Cyclic inheritance is detected and falls back to the built-in `default` metadata for the affected child while keeping that child's valid overrides. ### Structure and color scheme `extends` selects the parent theme. The child inherits its structural preset, color scheme, density, and tokens. `colorScheme`, `defaultRowSize`, and child tokens override their inherited values without coupling behavior to the custom theme name. ```ts const highContrastCompact = defineTheme({ name: 'highContrastCompact', extends: 'compact', colorScheme: 'dark', tokens: { background: '#000', text: '#fff', cellBorder: '#777', }, }) ``` Darkness is resolved from `colorScheme`; RevoGrid does not infer it from words in `name`. ### Extend another custom theme Register the parent and child definitions on the same grid. Definition order does not affect inheritance; duplicate names still use the last definition in the array. ```ts const productTheme = defineTheme({ name: 'product', extends: 'material', defaultRowSize: 38, tokens: { primary: '#2563eb', background: '#f8fafc', text: '#0f172a', headerBg: '#e2e8f0', }, }) const billingTheme = defineTheme({ name: 'billing', extends: productTheme.name, tokens: { primary: '#7c3aed', headerBg: '#ede9fe', }, }) grid.themeDefinitions = [productTheme, billingTheme] grid.theme = billingTheme.name ``` `billing` inherits the material structure, 38 px density, background, and text from `product`, then replaces only `primary` and `headerBg`. ## Precedence Theme values resolve in this order, from lowest to highest priority: 1. built-in fallback values at the root of the inheritance chain 2. inherited or grid-level CSS custom properties 3. ancestor `ThemeDefinition` tokens, from root to immediate parent 4. tokens from the active child `ThemeDefinition` 5. a positive `rowSize` property for row geometry This means application CSS is a convenient default, while a reusable typed preset remains deterministic on the grid using it. ## Density and row sizes `defaultRowSize` belongs to the theme definition. The public `rowSize` property is an explicit grid override: ```ts grid.rowSize = 44 grid.theme = 'compact' grid.theme = 'material' // Rows remain 44 px across both switches. grid.rowSize = 0 // The active theme's defaultRowSize applies again. ``` Custom entries in `rowDefinitions` remain in force when the theme density changes. RevoGrid updates virtual geometry only when the effective row size changes; color-only token changes do not reset row geometry. ## Runtime updates ```ts grid.addEventListener('afterthemechanged', (event) => { console.log(event.detail) // normalized string name }) grid.theme = 'billing' grid.themeDefinitions = [ { ...billingTheme, tokens: { ...billingTheme.tokens, primary: '#ffb86b' }, }, ] ``` Assign a new `themeDefinitions` array when changing a definition. This matches React, Vue, Angular, and Svelte change-detection conventions and ensures the grid reapplies the active preset. Definitions are registered per grid. Two grids may use the same custom name with different definitions without leaking styles or configuration between instances. ## Modern preset collection RevoGrid exports five opt-in presets built with the same public `ThemeDefinition` API. They are ordinary definitions rather than additional structural modes, so applications only ship and register the designs they use. | Preset | Direction | Base | Row height | | ------------------ | ----------------------------------------------------------- | -------------- | ---------: | | `ocean` | Airy blue and slate for light workspaces | `material` | 38 px | | `midnight` | Deep navy with cyan and violet accents | `darkMaterial` | 40 px | | `aurora` | Compact graphite with luminous green states | `darkCompact` | 34 px | | `highContrast` | Strong light surfaces, borders, and blue focus states | `material` | 40 px | | `highContrastDark` | Near-black surfaces with yellow and cyan interaction states | `darkMaterial` | 40 px | Register the full collection: ```ts import { modernThemeDefinitions } from '@revolist/revogrid' grid.themeDefinitions = modernThemeDefinitions grid.theme = 'midnight' ``` Or import one independently to keep configuration explicit: ```ts import { oceanTheme } from '@revolist/revogrid' grid.themeDefinitions = [oceanTheme] grid.theme = oceanTheme.name ``` Curated presets can also serve as parents. Register the preset alongside the child definition: ```ts import { defineTheme, oceanTheme } from '@revolist/revogrid' const brandedOcean = defineTheme({ name: 'brandedOcean', extends: oceanTheme.name, tokens: { primary: '#db2777', buttonBg: '#db2777', }, }) grid.themeDefinitions = [oceanTheme, brandedOcean] grid.theme = brandedOcean.name ``` For accessibility-focused registration, import only the dedicated collection: ```ts import { highContrastThemeDefinitions } from '@revolist/revogrid' grid.themeDefinitions = highContrastThemeDefinitions grid.theme = 'highContrastDark' ``` The exports are `oceanTheme`, `midnightTheme`, `auroraTheme`, `highContrastTheme`, `highContrastDarkTheme`, `highContrastThemeDefinitions`, and `modernThemeDefinitions`. The high-contrast presets provide stronger default differentiation, but application overrides and custom cell renderers still need their own accessibility review. Since definitions remain per-grid, their names can be replaced by a later definition in your own array without affecting another grid. ## Framework examples All framework wrappers pass `themeDefinitions` as an object-valued property. ::: code-group ```tsx [React] import { RevoGrid } from '@revolist/react-datagrid' import { defineTheme } from '@revolist/revogrid' const themes = [ defineTheme({ name: 'brand', extends: 'material', tokens: { primary: '#6d4aff', headerBg: '#f0edff' }, }), ] export function Grid() { return ( ) } ``` ```vue [Vue 3] ``` ```ts [Angular] import { Component } from '@angular/core' import { RevoGrid, defineTheme } from '@revolist/angular-datagrid' @Component({ standalone: true, imports: [RevoGrid], template: ` `, }) export class AppComponent { themes = [ defineTheme({ name: 'brand', extends: 'material', tokens: { primary: '#6d4aff', headerBg: '#f0edff' }, }), ] } ``` ```svelte [Svelte] ``` ```python [Dash] from dash_datagrid import RevoGrid RevoGrid( columns=columns, source=rows, theme="brand", themeDefinitions=[{ "name": "brand", "extends": "material", "tokens": { "primary": "#6d4aff", "headerBg": "#f0edff", }, }], style={"height": 420}, ) ``` ::: ## Public theme tokens Token keys are type checked by `ThemeTokens`. Each key maps to an inheritable CSS custom property. ### Foundation and grid states | Token | CSS custom property | | -------------------- | --------------------------------- | | `primary` | `--revo-grid-primary` | | `primaryTransparent` | `--revo-grid-primary-transparent` | | `background` | `--revo-grid-background` | | `foreground` | `--revo-grid-foreground` | | `divider` | `--revo-grid-divider` | | `shadow` | `--revo-grid-shadow` | | `text` | `--revo-grid-text` | | `border` | `--revo-grid-border` | | `headerBg` | `--revo-grid-header-bg` | | `headerColor` | `--revo-grid-header-color` | | `headerBorder` | `--revo-grid-header-border` | | `headerFocusedBg` | `--revo-grid-header-focused-bg` | | `headerHoverBg` | `--revo-grid-header-hover-bg` | | `cellBorder` | `--revo-grid-cell-border` | | `cellVerticalBorder` | `--revo-grid-cell-vertical-border` | | `focusedBg` | `--revo-grid-focused-bg` | | `rowHover` | `--revo-grid-row-hover` | | `rowHeadersBg` | `--revo-grid-row-headers-bg` | | `rowHeadersColor` | `--revo-grid-row-headers-color` | | `cellDisabledBg` | `--revo-grid-cell-disabled-bg` | `cellVerticalBorder` is transparent by default for material and compact structures. Set it in a custom definition or with its CSS variable to opt into vertical separators; the `highContrastDark` preset enables it automatically. ### Typography and spacing | Token | CSS custom property | | --------------------- | ----------------------------------- | | `fontFamily` | `--revo-grid-font-family` | | `fontSize` | `--revo-grid-font-size` | | `headerHeight` | `--revo-grid-header-height` | | `headerFontSize` | `--revo-grid-header-font-size` | | `headerFontWeight` | `--revo-grid-header-font-weight` | | `headerTextTransform` | `--revo-grid-header-text-transform` | | `headerTextAlign` | `--revo-grid-header-text-align` | | `cellTextAlign` | `--revo-grid-cell-text-align` | | `headerPadding` | `--revo-grid-header-padding` | | `cellPadding` | `--revo-grid-cell-padding` | ### Selection, autofill, and resize | Token | CSS custom property | | -------------------------- | ---------------------------------------- | | `selectionBorder` | `--revo-grid-selection-border` | | `selectionBg` | `--revo-grid-selection-bg` | | `autofillHandleBg` | `--revo-grid-autofill-handle-bg` | | `autofillHandleBorder` | `--revo-grid-autofill-handle-border` | | `rangeHandleBg` | `--revo-grid-range-handle-bg` | | `temporaryRangeBorder` | `--revo-grid-temporary-range-border` | | `temporarySelectionBorder` | `--revo-grid-temporary-selection-border` | | `headerResizeHover` | `--revo-grid-header-resize-hover` | ### Filter panel | Token | CSS custom property | | -------------------------------- | ------------------------------------------------ | | `filterPanelBg` | `--revo-grid-filter-panel-bg` | | `filterPanelBorder` | `--revo-grid-filter-panel-border` | | `filterPanelShadow` | `--revo-grid-filter-panel-shadow` | | `filterPanelInputBg` | `--revo-grid-filter-panel-input-bg` | | `filterPanelDivider` | `--revo-grid-filter-panel-divider` | | `filterPanelSelectBorder` | `--revo-grid-filter-panel-select-border` | | `filterPanelSelectBorderHover` | `--revo-grid-filter-panel-select-border-hover` | | `filterPanelReorderAccent` | `--revo-grid-filter-panel-reorder-accent` | | `filterPanelReorderColor` | `--revo-grid-filter-panel-reorder-color` | | `filterPanelText` | `--revo-grid-filter-panel-text` | | `filterPanelMutedText` | `--revo-grid-filter-panel-muted-text` | | `filterPanelFocusRing` | `--revo-grid-filter-panel-focus-ring` | | `filterPanelIcon` | `--revo-grid-filter-panel-icon` | | `filterPanelIconActive` | `--revo-grid-filter-panel-icon-active` | | `filterPanelSelectArrow` | `--revo-grid-filter-panel-select-arrow` | | `filterPanelSelectArrowDisabled` | `--revo-grid-filter-panel-select-arrow-disabled` | ### Buttons | Token | CSS custom property | | --------------------- | ----------------------------------- | | `buttonText` | `--revo-grid-button-text` | | `buttonBg` | `--revo-grid-button-bg` | | `buttonSuccessBg` | `--revo-grid-button-success-bg` | | `buttonDangerBg` | `--revo-grid-button-danger-bg` | | `buttonOutlineBorder` | `--revo-grid-button-outline-border` | | `buttonOutlineText` | `--revo-grid-button-outline-text` | Token values are CSS strings. RevoGrid does not inject arbitrary CSS or global stylesheets; use normal selectors when token-level customization is not sufficient. --- # Real-Time Updates in RevoGrid Source: https://rv-grid.com/guide/realtime-updates Description: Learn how to stream live data into RevoGrid while keeping large datasets responsive with virtualization, targeted updates, and batched rendering. ::: info Live update demo The overview demo below uses the same grid setup pattern, then refreshes stock-like values on an interval. Scroll the grid while the data changes to see how virtualization keeps the visible area responsive. ::: RevoGrid works well for live dashboards, trading screens, monitoring tools, and operational grids where values change while users keep scrolling, filtering, or editing. The grid is virtualized by default, so frequent updates do not require every row and column to exist in the DOM at the same time. Start with the same setup from the quick start: define columns, assign a `source`, and let RevoGrid render the visible viewport. ```ts // Get the grid element from the page const grid = document.querySelector('revo-grid'); // Define the columns users will see grid.columns = [ { prop: 'name', name: 'Name' }, { prop: 'role', name: 'Role' }, ]; // Provide the rows to render grid.source = [ { name: 'Ada Lovelace', role: 'Mathematician' }, { name: 'Grace Hopper', role: 'Scientist' }, ]; ``` ## Update the whole source Use a full `source` assignment when your application receives a new snapshot, page, filter result, or server response. ```ts const rows = [ { id: 1, symbol: 'REV', price: 120.40 }, { id: 2, symbol: 'GRID', price: 88.10 }, ]; grid.columns = [ { prop: 'symbol', name: 'Symbol' }, { prop: 'price', name: 'Price' }, ]; grid.source = rows; setInterval(() => { grid.source = rows.map(row => ({ ...row, price: Number((row.price + (Math.random() - 0.5) * 4).toFixed(2)), })); }, 1000); ``` This is the simplest model and is usually enough for modest update rates. It also matches state-driven frameworks where the grid receives a fresh array after your store changes. ## Update one cell For frequent single-cell changes, use `setDataAt` so the grid can update a specific cell instead of replacing the full source. ```ts await grid.setDataAt({ row: 0, col: 1, val: 123.45, }); ``` Use this pattern for live prices, status indicators, counters, progress values, and telemetry cells where the row and column are already known. ## Batch fast streams If updates arrive faster than the browser should paint, collect them and flush once per animation frame. ```ts const pending = new Map(); let scheduled = false; function queuePrice(rowIndex: number, price: number) { pending.set(String(rowIndex), price); if (scheduled) return; scheduled = true; requestAnimationFrame(async () => { scheduled = false; for (const [rowIndex, price] of pending) { await grid.setDataAt({ row: Number(rowIndex), col: 1, val: price, }); } pending.clear(); }); } ``` Batching keeps high-frequency streams from fighting the browser render loop. It also gives your application a clear place to drop stale updates if newer values arrive for the same row. ## Keep virtualization enabled Real-time grids usually need virtualization more than static grids. Leave virtual rendering enabled for large row or column counts, and tune only when you understand the tradeoff. - Keep `disableVirtualY` off for large datasets. - Keep `disableVirtualX` off for wide grids. - Increase `frameSize` only if very fast scrolling shows blanking around the viewport. - Keep cell templates cheap because they may run many times while users scroll. See [Performance and Virtualization](https://rv-grid.com/guide/performance) for the detailed performance settings. ## Recommended update strategy Choose the update shape based on the incoming data: | Stream shape | Recommended approach | | --- | --- | | Complete server snapshot | Assign `grid.source` with the new rows | | Small number of known cells | Use `setDataAt` | | Bursty WebSocket messages | Queue updates and flush with `requestAnimationFrame` | | Server-side paging or filtering | Replace the current source page | | User edits plus live updates | Keep an application data store and reconcile edits before assigning source | ## Practical checklist - Assign `columns` once unless the schema actually changes. - Preserve row identity in your application store with stable IDs. - Batch rapid updates before touching the grid. - Avoid expensive custom cell templates for values that change often. - Use [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control) for targeted methods such as `setDataAt`. - Use [Data Source Loading and Syncing](https://rv-grid.com/guide/data-sync) when your app needs a clear source-of-truth strategy. --- # TypeScript Data Grid Source: https://rv-grid.com/guide/ts Description: Use RevoGrid as a TypeScript data grid with typed row models, reusable column definitions, public instance methods, and framework-agnostic APIs. RevoGrid is built in TypeScript and exposes typed APIs for columns, events, methods, plugins, and framework wrappers. If your app is already using TypeScript, you can treat the grid as a typed UI boundary rather than a loosely typed widget. ## What TypeScript gives you in RevoGrid - typed row models for `source` - typed column configuration with reusable `columnTypes` - typed event payloads for editing, filtering, focus, and source updates - typed instance methods such as `setDataAt`, `getVisibleSource`, and `getSelectedRange` ## Minimal typed setup ```ts interface PersonRow { id: number; name: string; email: string; } const grid = document.querySelector('revo-grid'); const columns = [ { prop: 'id', name: 'ID', readonly: true }, { prop: 'name', name: 'Name' }, { prop: 'email', name: 'Email' }, ]; const source: PersonRow[] = [ { id: 1, name: 'Ada Lovelace', email: 'ada@example.com' }, { id: 2, name: 'Grace Hopper', email: 'grace@example.com' }, ]; grid!.columns = columns; grid!.source = source; ``` ## Good TypeScript patterns - define a dedicated row interface for each grid - keep `prop` values aligned with actual row keys - extract shared `columnTypes` for repeated formatting and editor rules - type your event handlers when you need to inspect `detail` ## Where to go next - [Advanced Types](https://rv-grid.com/guide/types/README) - [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control) - [Advanced Configuration](https://rv-grid.com/guide/advanced-configuration) - [API Reference](https://rv-grid.com/guide/api/revoGrid) --- # Angular Data Grid Source: https://rv-grid.com/guide/angular Description: Learn how to use RevoGrid in Angular with standalone components or modules, pass columns and source data, and access the underlying grid API. RevoGrid shines in Angular when you want a high-performance grid without giving up framework-native templates and editors. The Angular wrapper keeps the grid convenient to use while still exposing the same core RevoGrid API. ::: info This tutorial assumes that an Angular project already exists. If not, start with the official [Angular installation guide](https://angular.dev/installation). ::: ## Install your Angular Data Grid Install [RevoGrid for Angular](https://github.com/revolist/angular-datagrid) using the following command: ::: code-group ```npm npm i @revolist/angular-datagrid ``` ```pnpm pnpm add @revolist/angular-datagrid ``` ```yarn yarn add @revolist/angular-datagrid ``` ```bun bun add @revolist/angular-datagrid ``` ::: ## Standalone component setup ```ts import { Component } from '@angular/core'; import { RevoGrid } from '@revolist/angular-datagrid'; @Component({ selector: 'app-root', standalone: true, imports: [RevoGrid], template: ``, }) export class AppComponent { source = [ { name: 'Item 1', details: 'First row' }, { name: 'Item 2', details: 'Second row' }, ]; columns = [ { prop: 'name', name: 'Name' }, { prop: 'details', name: 'Details' }, ]; } ``` ## Module-based setup If your Angular app still uses modules, RevoGrid can be imported there as well: ::: code-group ```ts [app.module.ts] import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { RevoGrid } from '@revolist/angular-datagrid'; import { AppComponent } from './app.component'; @NgModule({ declarations: [AppComponent], imports: [BrowserModule, RevoGrid], bootstrap: [AppComponent], }) export class AppModule {} ``` ```ts [app.component.ts] import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ``, }) export class AppComponent { source = [ { name: 'Item 1', details: 'First row' }, { name: 'Item 2', details: 'Second row' }, ]; columns = [ { prop: 'name', name: 'Name' }, { prop: 'details', name: 'Details' }, ]; } ``` ::: ::: warning Dynamic Component Usage When using RevoGrid with Angular 19+, there are known edge cases with dynamically loading or using the component in certain scenarios. The grid frame may render, but columns and source data may not display properly. **Known Symptoms:** - Columns and source data might not render when the component is used dynamically. - Plugins and readonly properties may stop working in some dynamic scenarios. - Silent errors might occur without any visible error messages. **Related GitHub Discussion:** [GitHub Discussion #798](https://github.com/revolist/revogrid/issues/798) **Helpful Resources:** - [Angular Component Communication](https://angular.dev/guide/components/inputs-outputs) - [Angular Standalone Components](https://angular.dev/guide/components/importing) - [Angular Router Outlet](https://angular.dev/api/router/RouterOutlet) If you encounter issues with dynamic component usage, please report them on [GitHub Issues](https://github.com/revolist/revogrid/issues) with details about your Angular version and setup. ::: ## Accessing grid instance methods When you need to call public methods such as `scrollToRow`, `setCellEdit`, or `getVisibleSource`, grab the underlying element and call the API on that instance. ## Custom renderers and editors Use these Angular-specific guides for deeper integration: - [Angular Cell Template](https://rv-grid.com/guide/angular/renderer) - [Angular Cell Editor](https://rv-grid.com/guide/angular/editor) ## Event handling Angular applications typically listen to the same RevoGrid lifecycle events as other integrations: - `beforeedit` - `afteredit` - `beforefilterapply` - `beforesourceset` ## Related guides - [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control) - [Advanced Configuration](https://rv-grid.com/guide/advanced-configuration) - [Event Patterns and Lifecycles](https://rv-grid.com/guide/events-guide) - [Grid Performance and Virtualization](https://rv-grid.com/guide/performance) ## Check out our Angular Data Grid examples --- # Angular Data Grid Cell Template Source: https://rv-grid.com/guide/angular/renderer Description: Cell template rendering in Angular Data Grid, enabling custom Angular components inside grid cells. RevoGrid provide a way to render native components inside of cells. ::: warning If you are aiming for the faster render we are recommending to stick with native VNode render. ::: ::: tip Check [ColumnDataSchemaModel](https://rv-grid.com/guide/types/TypeAlias.ColumnDataSchemaModel) for mode information about input types. ::: [![Edit RG Cell (Angular Standalone)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-cell-angular-standalone-t4lrz2) ## Why Use Custom Cell Rendering? RevoGrid’s native cell rendering enables you to: - **Embed Components**: Render complex or interactive UI elements inside grid cells, such as buttons, images, input fields, or custom widgets. - **Dynamic Content**: Customize each cell’s content based on the data it represents, such as formatting or conditional rendering. - **Interactivity**: Make cells interactive with event listeners and component lifecycle methods, improving the overall user experience. ## Cell Component First, let's create a component to be displayed as a cell. This component will receive the cell's properties as an input and display it. ```ts // cell.component.ts import { Component, Input } from '@angular/core'; import { ColumnDataSchemaModel } from '@revolist/revogrid'; @Component({ selector: 'app-cell', standalone: true, template: ' {{value}} works!', }) export class CellComponent { @Input() props!: ColumnDataSchemaModel; get value() { return this.props.rowIndex; } } ``` ## Grid Component and Cell Template Next let's create a component that will be used to render the grid. This component will receive the grid's properties as an input and display it. At the same time, it will set the cell's template as native element of the cell. ```ts // app.component.ts import { Component } from "@angular/core"; import { RevoGrid, Template } from "@revolist/angular-datagrid"; import { CellComponent } from "./cell.component"; @Component({ selector: "app-root", standalone: true, imports: [RevoGrid, CellComponent], template: ``, }) export class AppComponent { source = [ { name: "1", details: "Item 1", }, { name: "2", details: "Item 2", }, ]; columns = [ { prop: "name", name: "First", cellTemplate: Template(CellComponent), }, { prop: "details", name: "Second", }, ]; } ``` ## Check out our Angular Data Grid examples --- # Angular Data Grid Editor Source: https://rv-grid.com/guide/angular/editor Description: Learn how to implement editor in Data Grid with Angular, enabling custom in-cell editing using Angular components. RevoGrid provides a way to render native components as editor. ::: tip You can access close and save callbacks in properties. Check [editor](https://rv-grid.com/guide/cell/editor) and `EditorCtr` type for more. ::: # Native Editor Component Demo [![Edit RG Editor (Angular Standalone)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-editor-angular-standalone-lgc3pr) ## Editor as standalone component First we need to create a custom editor component. ```ts // editor.component.ts import { Component, Input } from "@angular/core"; import { type EditorType } from "@revolist/angular-datagrid"; @Component({ selector: "app-editor", standalone: true, template: '', }) export class EditorComponent { @Input() props!: EditorType; testClick() { this.props.close(); } } ``` ## Grid Component and Editor Next, let's create standalone component that will be used to render the grid. Now we can render the grid with the custom editor component. ```ts // app.component.ts import { Component } from "@angular/core"; import { RevoGrid, Editor, type Editors, type ColumnRegular, } from "@revolist/angular-datagrid"; import { EditorComponent } from "./editor.component"; const MY_EDITOR = "custom-editor"; @Component({ selector: "app-root", standalone: true, imports: [RevoGrid, EditorComponent], template: ``, }) export class AppComponent { source = [ { name: "1", details: "Item 1", }, { name: "2", details: "Item 2", }, ]; columns: ColumnRegular[] = [ { prop: "name", name: "First", // define editor editor: MY_EDITOR, }, { prop: "details", name: "Second", }, ]; // provide editor classes editors: Editors = { [MY_EDITOR]: Editor(EditorComponent) }; } ``` ## Check out our Angular Data Grid examples --- # Angular Tree Data Grid Source: https://rv-grid.com/guide/angular/tree Description: Build an Angular tree data grid with the free RevoGrid core tree pattern, then upgrade to RevoGrid Pro TreeDataPlugin for expandable hierarchy controls, sticky parents, and drag-and-drop. Angular applications can start with the free/core tree pattern by preparing a flat `source` array in the component and rendering indentation through a cell template. ::: info The core tree pattern does not require Pro plugins. The current live `core-tree` widget is published for TypeScript, React, and Vue; Angular uses the same flattened `source` and cell-template approach. ::: Tree-like rows do not require Pro when your application only needs a visual hierarchy. The free/core approach is to flatten parent-child records into display order, add a `level` field, and render indentation in a cell template. This keeps RevoGrid simple: the grid receives a normal `source` array, virtualization still works, and your application owns the hierarchy transformation. ## Tree model Start with records that have an ID and a parent ID: ```ts const inputData = [ { id: 4, parentId: 0, name: 'Antoni father for 2' }, { id: 5, parentId: 4, name: 'Odin' }, { id: 6, parentId: 4, name: 'John' }, { id: 1, parentId: 0, name: 'Mary mother for 2' }, { id: 2, parentId: 1, name: 'Howard has also 2' }, ]; ``` Convert that data into a flat display list before assigning it to the grid: ```ts function buildTreeData(rows: typeof inputData, rootParentId = 0) { const childrenByParent = new Map(); for (const row of rows) { const children = childrenByParent.get(row.parentId) ?? []; children.push(row); childrenByParent.set(row.parentId, children); } const result: Array<(typeof inputData)[number] & { level: number }> = []; function appendChildren(parentId: number, level = 0) { for (const child of childrenByParent.get(parentId) ?? []) { result.push({ ...child, level }); appendChildren(child.id, level + 1); } } appendChildren(rootParentId); return result; } ``` ## Indented cell template The core demo uses a normal cell template to show hierarchy depth: ```ts const columns = [ { prop: 'name', name: 'Tree', size: 300, cellTemplate(h, { value, model }) { return h( 'div', { style: { marginLeft: `${(model?.level ?? 0) * 30}px`, }, }, value || '', ); }, }, { prop: 'level', readonly: true, }, ]; ``` Use the core approach when the hierarchy is read-only or mostly decorative: category outlines, simple nested lists, document sections, or a tree table where your app handles all expand/collapse logic outside the grid. ## Core limits The free/core pattern is intentionally lightweight. It does not add built-in expand/collapse controls, automatic parent-child visibility, tree-aware drag-and-drop, sticky parent rows, or parent/descendant row selection behavior. Those behaviors belong in the Pro Tree Data plugin. ## Angular notes - Build `source` from your component, service, signal, or store. - Bind `[columns]` and `[source]` normally; no Pro plugin is needed for the core tree. - Keep the tree transformation separate from the component template. ```ts ``` ## Pro Tree Data RevoGrid Pro adds a dedicated `TreeDataPlugin` for advanced data grid tree structures. It keeps the original `source` flat, computes hierarchy metadata internally, and renders tree controls in the column marked with `tree: true`. ::: info RevoGrid Pro Use the Pro plugin when hierarchy is not just indentation: users need expand/collapse controls, persistent expansion state, filtering and sorting with hierarchy awareness, row selection across descendants, drag-and-drop reparenting, or sticky parent rows while scrolling long branches. ::: ### Pro data model The Pro model also starts from stable IDs and parent IDs: ```ts type TeamRow = { id: string; parentId: string | null; name: string; role: string; budget: number; }; const source: TeamRow[] = [ { id: 'eng', parentId: null, name: 'Engineering', role: 'Department', budget: 850000 }, { id: 'platform', parentId: 'eng', name: 'Platform', role: 'Team', budget: 320000 }, { id: 'api', parentId: 'platform', name: 'API', role: 'Squad', budget: 140000 }, { id: 'design', parentId: null, name: 'Design', role: 'Department', budget: 260000 }, ]; ``` Unlike the core example, you do not add `level` yourself. The plugin derives level, visibility, expanded state, and child metadata from the tree config. ### Pro column and plugins Mark one hierarchy column with `tree: true`, register `TreeDataPlugin`, and pass the `tree` config: ```ts import { TreeDataPlugin, RowOrderPlugin, RowSelectPlugin, StickyCellsPlugin, TREE_EXPAND_ALL_EVENT, TREE_COLLAPSE_ALL_EVENT, } from '@revolist/revogrid-pro'; const columns = [ { prop: 'name', name: 'Team', size: 300, tree: true, sortable: true, rowSelect: true, rowDrag: true, }, { prop: 'role', name: 'Role', size: 160 }, { prop: 'budget', name: 'Budget', size: 140 }, ]; const plugins = [ TreeDataPlugin, RowOrderPlugin, RowSelectPlugin, StickyCellsPlugin, ]; const tree = { idField: 'id', parentIdField: 'parentId', rootParentId: null, expandedRowIds: new Set(['eng']), stickyParents: true, }; ``` Framework wrappers pass these values as props or bindings. Plain TypeScript assigns them to the `revo-grid` element. ### Expand and collapse controls The Pro plugin exposes events for toolbar buttons and external controls: ```ts grid.dispatchEvent(new CustomEvent(TREE_EXPAND_ALL_EVENT)); grid.dispatchEvent(new CustomEvent(TREE_COLLAPSE_ALL_EVENT)); ``` Use `expandAll: true` when every branch should open on first render. Use `expandedRowIds` when you want controlled initial state or persisted expansion. ### Production guidance - Keep IDs stable across refreshes so expanded state survives data updates. - Use `parentId: null` or another explicit `rootParentId` consistently. - Keep only one tree column active; use normal columns for the rest of the row data. - Combine tree data with virtualization for large hierarchies instead of rendering nested DOM lists. - Add `StickyCellsPlugin` only when sticky parent rows are useful for long branches. - Reconcile drag-and-drop changes in your application store before saving to the backend. - Prefer flat server payloads for large trees; they are simpler to page, diff, validate, and persist. ## Related guides - [Advanced Tree Data guide](https://rv-grid.com/guide/tree-data) - [Row Ordering](https://rv-grid.com/guide/row/order) - [Row Selection](https://rv-grid.com/guide/row/selection.pro) - [Filtering](https://rv-grid.com/guide/filters) - [Grid Performance and Virtualization](https://rv-grid.com/guide/performance) --- # React Data Grid Source: https://rv-grid.com/guide/react Description: Learn how to use RevoGrid in React with typed props, refs to the underlying grid instance, custom renderers, custom editors, and event handling. RevoGrid gives React applications a fast virtualized data grid without changing the core grid behavior. You pass `columns` and `source` as props, then use a ref when you need to call instance methods such as `setCellEdit`, `scrollToRow`, or `getVisibleSource`. ## Install your React Data Grid Install [RevoGrid for React](https://github.com/revolist/react-datagrid) using the following command: ::: code-group ```npm npm i @revolist/react-datagrid ``` ```pnpm pnpm add @revolist/react-datagrid ``` ```yarn yarn add @revolist/react-datagrid ``` ```bun bun add @revolist/react-datagrid ``` ::: ## Minimal setup ```tsx // App.tsx import { RevoGrid } from '@revolist/react-datagrid' import { useState } from 'react' /** * note: columns & source need a "stable" reference in order to prevent infinite re-renders */ const columns = [ { prop: 'name', name: 'First', }, { prop: 'details', name: 'Second', }, ] function App() { const [source] = useState([ { name: '1', details: 'Item 1', }, { name: '2', details: 'Item 2', }, ]) return ( <> ) } export default App ``` # React Data Grid Demo Use this React demo to start a RevoGrid table with virtualized rows and columns, editable cells, and high-performance rendering for large datasets. [![Edit react-revogrid-start](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/react-revogrid-start-29fm5z) ## Working with `columns` and `source` In React, the most maintainable pattern is: - keep `columns` stable unless configuration really changed - update `source` from application state - use grid methods for imperative actions instead of reaching into internal DOM ## Accessing grid instance methods Use a ref to the wrapped grid element, then call the public API on the underlying instance: ```tsx import { useRef } from 'react'; function App() { const gridRef = useRef(null); const focusFirstPriceCell = async () => { await gridRef.current?.scrollToRow?.(0); await gridRef.current?.setCellEdit?.(0, 'price'); }; return ( <> ); } ``` ## Custom renderers and editors Use these pages for React-specific customization: - [React Cell Template](https://rv-grid.com/guide/react/renderer) - [React Cell Editor](https://rv-grid.com/guide/react/editor) ## Event handling React apps usually listen for the same grid events as plain JavaScript: - `beforeedit` - `afteredit` - `beforefilterapply` - `beforesourceset` If you need to shape event-driven workflows, start with [Event Patterns and Lifecycles](https://rv-grid.com/guide/events-guide). ## SSR and client-only behavior RevoGrid depends on browser APIs, so server-rendered React environments should load it on the client side. If your app uses Next.js or another SSR framework, render the grid in a client component or dynamically load it on the client. ## Related guides - [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control) - [Advanced Configuration](https://rv-grid.com/guide/advanced-configuration) - [Grid Performance and Virtualization](https://rv-grid.com/guide/performance) ## Check out our React Data Grid examples --- # React Data Grid Cell Template Support Source: https://rv-grid.com/guide/react/renderer Description: React cell template support in RevoGrid for React, allowing the use of custom React components inside grid cells. # React Data Grid Cell Template RevoGrid provide a way to render native components inside of cells. ::: warning If you are aiming for the faster render we are recommending to stick with native VNode render. ::: ::: tip Check [ColumnDataSchemaModel](https://rv-grid.com/guide/types/TypeAlias.ColumnDataSchemaModel) for mode information about input types. ::: This capability, known as native cell rendering, allows developers to customize how the grid cells are displayed, providing a high degree of control over their appearance and behavior. # React Custom Cell Template Demo [![Edit react-revogrid-cell](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/react-revogrid-cell-jgt3mv) ### Key Considerations for Custom Cell Templates - **Data Access**: Each custom cell component will have access to the data for that row via its props. The primary prop that is passed to custom renderers is the value of the cell. - **Performance**: Custom renderers can impact grid performance, especially with large datasets. RevoGrid optimizes rendering by only updating cells that have changed, but it’s important to keep performance in mind when creating complex cell templates. - **Conditional Rendering**: You can use conditional logic inside your custom cell component to change its appearance based on the data. For example, you can display different colors or icons based on numeric values or boolean flags. - **Event Handling**: Custom cells can include event handlers, such as onClick, onChange, etc., to make the grid interactive. This is ideal for rendering editable fields, buttons, or custom controls. ### Advanced Use Cases RevoGrid’s native rendering support opens up even more complex scenarios where you can render interactive components, such as: - **Dynamic Dropdowns**: Populate a dropdown inside a cell based on the data in the grid or external sources. - **Custom Formatting**: Display values with custom formatting, such as currency symbols, percentages, or styled numbers. - **Inline Editing**: Build advanced inline editing components, such as date pickers, checkboxes, or toggles, inside grid cells. In this guide, we will explore how to implement custom cell renderers and templates within your RevoGrid in React. Whether you need to render custom React components, include dynamic data, or create interactive cell behaviors, RevoGrid’s native rendering support ensures that your cells are more than just plain text. ## Why Use Custom Cell Rendering? RevoGrid’s native cell rendering enables you to: - **Embed Components**: Render complex or interactive UI elements inside grid cells, such as buttons, images, input fields, or custom widgets. - **Dynamic Content**: Customize each cell’s content based on the data it represents, such as formatting or conditional rendering. - **Interactivity**: Make cells interactive with event listeners and component lifecycle methods, improving the overall user experience. ## Basic Setup Here’s an example of how you can use a simple React component to render custom content inside a grid cell. ```tsx{10-12,21} // App.tsx import { type ColumnDataSchemaModel, RevoGrid, Template } from '@revolist/react-datagrid'; import { useState } from 'react' /** * Custom cell component */ const Cell = ({ value }: Partial) => { return
{value}
; }; /** * note: columns & source need a "stable" reference in order to prevent infinite re-renders */ const columns = [ { prop: 'name', name: 'First', cellTemplate: Template(Cell), }, ]; function App() { const [source] = useState([ { name: '1', details: 'Item 1', }, ]); return ( <> ) } export default App; ``` In the example above: - We define a `Cell` component that accepts a value prop and renders it inside a `span` element with custom styles. - The columns definition includes the `cellTemplate` property, which references the `Cell` component. - RevoGrid automatically uses `Cell` to render the name column. ## Check out our React Data Grid examples --- # React Data Grid Editor Source: https://rv-grid.com/guide/react/editor Description: Learn how to implement editor in Data Grid with React, enabling custom in-cell editing using React components. RevoGrid provides a way to render native components as editor. ::: tip You can access close and save callbacks in properties. Check [editor](https://rv-grid.com/guide/cell/editor) and `EditorCtr` type for more. ::: By integrating React components as native editors, RevoGrid gives you full control over how each cell behaves during the editing process, enabling complex and highly interactive editing scenarios. # React Data Grid Cell Editor Demo RevoGrid allows for even more complex custom editors by passing data and handling events like onChange or onBlur. You can create more interactive editors such as input fields, checkboxes, or dropdowns that allow users to update cell values directly. [![Edit react-revogrid-editor](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/react-revogrid-cell-vdjyp2) ### Advanced Use Cases You can extend RevoGrid’s native editor rendering by implementing more sophisticated editors, such as: - **Date Pickers**: Use a date picker React component to edit date values in a column. - **Select Menus**: Render a dropdown menu with dynamic options based on other grid data or external sources. - **Multistep Editors**: Create complex multi-field editors for advanced data entry. ## Why Use Custom Editors? With native editor rendering, you can: - **Customize the Editing Experience**: Use any React component as a custom editor, providing a tailored user interface for editing data directly in the grid. - **Build Complex Editors**: Embed interactive elements such as date pickers, dropdowns, or custom forms inside cells, which would be impossible with simple input fields alone. - **Improve Usability**: Create inline editors that match your application’s UI, improving consistency and enhancing the overall user experience. ## Basic Setup RevoGrid allows you to define custom editors for grid cells using the editor property on columns. You can then assign React components to handle the rendering and editing of cell values. In this example, we’ll create a custom button editor that, when clicked, closes the editor. This demonstrates how you can use React components as editors. ```tsx{4,10-12,22,34} // App.tsx import { RevoGrid, Editor, type EditorType, type Editors } from '@revolist/react-datagrid'; import { useState } from 'react' /** * Custom editor component */ const Button = ({ close }: EditorType) => { return }; const MY_EDITOR = 'custom-editor'; /** * note: columns & source need a "stable" reference in order to prevent infinite re-renders */ const columns = [ { prop: 'name', name: 'First', editor: MY_EDITOR, }, ]; function App() { const [source] = useState([ { name: '1', details: 'Item 1', }, ]); const gridEditors: Editors = { [MY_EDITOR]: Editor(Button) }; return ( <> ) } export default App; ``` ### Key Components - **Custom Editor**: The Button component is a simple React component that will be used as a custom editor for the “First” column. When clicked, it will close the editor. - **Editor Registration**: The gridEditors object registers the custom editor using the Editor function. In this case, it links the custom editor (the Button component) to the identifier MY_EDITOR. - **Editor Prop**: In the columns array, the editor property is set to MY_EDITOR, indicating that the custom editor should be used for the “First” column. ## Check out our React Data Grid examples --- # Dash Data Grid Source: https://rv-grid.com/guide/dash Description: Install and use RevoGrid Core in Plotly Dash with typed Python props, DataFrame records, editing, sorting, filtering, and JSON-safe callbacks. [`dash-datagrid`](https://github.com/revolist/dash-datagrid) is the official RevoGrid Core integration for [Plotly Dash](https://dash.plotly.com/). It exposes the grid as the generated Python component `dash_datagrid.RevoGrid` and packages the required JavaScript with the Python distribution. Use this integration when the application layout and callbacks are written in Python, while the virtualized grid runs in the browser. ## Guides - [Getting Started](https://rv-grid.com/guide/dash/getting-started) — install the package and run your first grid. - [DataFrames](https://rv-grid.com/guide/dash/dataframes) — load JSON-safe rows and pandas DataFrames. - [Columns](https://rv-grid.com/guide/dash/columns) — configure columns and common grid features. - [Callbacks and Events](https://rv-grid.com/guide/dash/callbacks-and-events) — receive grid events in Dash callbacks. - [Edit Synchronization](https://rv-grid.com/guide/dash/edit-synchronization) — choose compact edit deltas or complete source synchronization. - [Property Reference](https://rv-grid.com/guide/dash/property-reference) — review supported properties and Python boundary limitations. - [Core API Reference](https://rv-grid.com/guide/dash/core-api-reference) — find the complete RevoGrid API documentation. ## Packages and compatibility | Distribution | Name | Purpose | | --- | --- | --- | | PyPI | [`dash-datagrid`](https://github.com/revolist/dash-datagrid) | Normal installation for a Dash application | | Python import | `dash_datagrid` | Exports `RevoGrid` | | npm | [`@revolist/dash-datagrid`](https://github.com/revolist/dash-datagrid) | JavaScript distribution used by the generated Dash component | The Python package supports Python 3.10 or newer and Dash 3.x or 4.x. A normal Python application only installs [`dash-datagrid`](https://github.com/revolist/dash-datagrid); Dash serves the packaged JavaScript locally, so a separate npm install is not required. Version 1 covers RevoGrid Core. Pro and Enterprise plugin activation, custom JavaScript renderers or editors, imperative methods, and synchronous client-side cancellation are not exposed through the Python component. --- # Dash Getting Started Source: https://rv-grid.com/guide/dash/getting-started Description: Install Dash DataGrid and run your first RevoGrid application in Plotly Dash. ## Packages and compatibility | Distribution | Name | Purpose | | --- | --- | --- | | [PyPI](https://pypi.org/project/dash-datagrid/) | [`dash-datagrid`](https://github.com/revolist/dash-datagrid) | Python package for a normal Dash application | | Python import | `dash_datagrid` | Exports `RevoGrid` | | [npm](https://www.npmjs.com/package/@revolist/dash-datagrid) | [`@revolist/dash-datagrid`](https://github.com/revolist/dash-datagrid) | Generated React bridge and bundled RevoGrid custom element | The Python package supports Python 3.10 or newer and Dash 3.x or 4.x. A normal Python application only installs [`dash-datagrid`](https://github.com/revolist/dash-datagrid); Dash serves the packaged JavaScript locally, so a separate npm install is not required. The current distributions cover RevoGrid Core. Pro and Enterprise plugin activation, custom JavaScript renderers or editors, imperative methods, and synchronous client-side cancellation are not exposed through the Python component. ## Build your first grid ### 1. Create an environment ```bash python -m venv .venv source .venv/bin/activate ``` On Windows PowerShell, activate it with: ```powershell .venv\Scripts\Activate.ps1 ``` ### 2. Install Dash DataGrid with Python ```bash python -m pip install dash-datagrid ``` This installs the official [`dash-datagrid` package from PyPI](https://pypi.org/project/dash-datagrid/) and its compatible Dash dependency automatically. To use the DataFrame examples, install pandas too: ```bash python -m pip install pandas ``` ### npm installation Use the npm distribution only when consuming or extending the generated React/JavaScript bridge directly. A standard Python Dash application does not need this step. ```bash npm install @revolist/dash-datagrid ``` The npm package requires Node.js 22 or newer. React and ReactDOM 18.3.1 or newer within the React 18 release line are peer dependencies: ```bash npm install react@^18.3.1 react-dom@^18.3.1 ``` ### 3. Create `app.py` ```python from dash import Dash, Input, Output, callback, html from dash_datagrid import RevoGrid app = Dash(__name__) app.layout = html.Main( [ html.H1("Orders"), RevoGrid( id="orders-grid", columns=[ { "prop": "order", "name": "Order", "readonly": True, "size": 130, }, { "prop": "customer", "name": "Customer", "sortable": True, "size": 180, }, { "prop": "amount", "name": "Amount", "sortable": True, "filter": "number", }, ], source=[ {"order": "A-100", "customer": "Ada", "amount": 120}, {"order": "A-101", "customer": "Grace", "amount": 85}, {"order": "A-102", "customer": "Linus", "amount": 210}, ], rowHeaders=True, resize=True, range=True, filter=True, style={"height": 420}, ), html.Pre("Edit a cell to see its event.", id="edit-output"), ] ) @callback( Output("edit-output", "children"), Input("orders-grid", "afteredit"), prevent_initial_call=True, ) def show_edit(event): detail = event["detail"] if "prop" not in detail: return f"Range edit: {detail}" return ( f'Row {detail["rowIndex"]}, {detail["prop"]} ' f'changed to {detail["val"]!r}' ) if __name__ == "__main__": app.run(debug=True) ``` Every column `prop` maps to a key in each source row. Set an explicit component height in `style`; the grid fills its Dash host, and the host needs a usable height. ### 4. Run the application ```bash python app.py ``` Open the local address printed by Dash, normally `http://127.0.0.1:8050`. ### Complete example project The [`examples/` project](https://github.com/revolist/dash-datagrid/tree/main/examples) includes a dependency manifest, DataFrame normalization, responsive styling, Python-driven source changes, dedicated callbacks, and generic event listeners. ```bash git clone https://github.com/revolist/dash-datagrid.git cd dash-datagrid/examples python -m venv .venv source .venv/bin/activate python -m pip install -r requirements.txt python app.py ``` --- # Dash DataFrames Source: https://rv-grid.com/guide/dash/dataframes Description: Load JSON-safe rows and pandas DataFrames into RevoGrid for Plotly Dash. ## Source rows `source`, `pinnedTopSource`, and `pinnedBottomSource` accept lists of JSON-serializable row objects: ```python rows = [ {"id": 1, "product": "Keyboard", "price": 95.0}, {"id": 2, "product": "Mouse", "price": 35.5}, ] ``` Values that cross the Dash boundary should be strings, finite numbers, booleans, `None`, lists, or dictionaries containing those values. Convert `datetime`, `Decimal`, NumPy scalar, UUID, and other Python-specific values before assigning a prop. See [Data & Rows](https://rv-grid.com/guide/row) for the Core row model and [Data Source Loading and Syncing](https://rv-grid.com/guide/data-sync) for source ownership patterns. ## pandas DataFrames For a DataFrame containing only JSON-native values, records are enough: ```python rows = frame.to_dict("records") grid = RevoGrid(columns=columns, source=rows, style={"height": 420}) ``` For dates, missing values, NumPy values, or other pandas-specific types, use a JSON round trip to normalize the records: ```python import json rows = json.loads( frame.to_json( orient="records", date_format="iso", ) ) ``` This converts timestamps to ISO strings and missing values to JSON `null`, which arrives in Python callbacks as `None`. ## Python-driven updates Return a new `source` when the application intentionally loads a different dataset: ```python from dash import Input, Output, callback @callback( Output("orders-grid", "source"), Input("reload-orders", "n_clicks"), prevent_initial_call=True, ) def reload_orders(_clicks): return load_orders_from_database() ``` Full source replacement is appropriate for reloads, searches, pagination, or dataset changes. For a normal cell edit, prefer the compact `afteredit` event described in [Edit synchronization](https://rv-grid.com/guide/dash/edit-synchronization). --- # Dash Columns Source: https://rv-grid.com/guide/dash/columns Description: Configure RevoGrid columns and common grid features in Plotly Dash. # Columns A column is a plain dictionary. `prop` is required and selects the value from each source row. ```python columns = [ { "prop": "id", "name": "ID", "readonly": True, "pin": "colPinStart", "size": 90, }, { "prop": "customer", "name": "Customer", "sortable": True, "minSize": 140, }, { "prop": "amount", "name": "Amount", "sortable": True, "filter": "number", "order": "desc", }, ] ``` Common JSON-safe column fields are: | Field | Purpose | | --- | --- | | `prop` | Row key used by the column | | `name` | Header label | | `size`, `minSize`, `maxSize` | Width constraints in pixels | | `readonly` | Disable editing for the column | | `sortable`, `order` | Enable sorting and set `asc` or `desc` order | | `filter` | Enable a string, number, or other built-in filter family | | `pin` | Use `colPinStart` or `colPinEnd` | | `rowDrag` | Add a row-drag handle | | `columnType` | Apply a preset from the grid-level `columnTypes` prop | Function-valued column members are not supported in v1. This includes `cellTemplate`, `columnTemplate`, `cellProperties`, `columnProperties`, `cellCompare`, `cellParser`, constructor-based `editor` values, function-based `readonly`, and function-based `rowDrag`. Use the [Column Configuration guide](https://rv-grid.com/guide/column), the complete [`ColumnRegular` interface](https://rv-grid.com/guide/types/Interface.ColumnRegular), and the [`ColumnGrouping` interface](https://rv-grid.com/guide/types/Interface.ColumnGrouping) to inspect the Core schema. When reading those pages, remember that Dash can use only primitive and plain-object members. ### Column groups Nested header groups are plain objects and therefore work across the Dash boundary: ```python columns = [ { "name": "Customer", "children": [ {"prop": "first_name", "name": "First name"}, {"prop": "last_name", "name": "Last name"}, ], }, { "name": "Order", "children": [ {"prop": "status", "name": "Status"}, {"prop": "amount", "name": "Amount", "filter": "number"}, ], }, ] ``` See [Column Grouping](https://rv-grid.com/guide/column/grouping). ### Reusable column types `columnTypes` can hold JSON-safe presets: ```python RevoGrid( columnTypes={ "identifier": {"readonly": True, "size": 120}, "money": {"size": 140, "sortable": True, "filter": "number"}, }, columns=[ {"prop": "id", "name": "ID", "columnType": "identifier"}, {"prop": "amount", "name": "Amount", "columnType": "money"}, ], source=rows, style={"height": 420}, ) ``` See [Column Types and Formats](https://rv-grid.com/guide/column/types) and [Advanced Configuration](https://rv-grid.com/guide/advanced-configuration#columntypes). ## Common feature recipes ### Editing, range selection, and clipboard ```python RevoGrid( source=rows, columns=columns, readonly=False, range=True, useClipboard={"rangeFill": True}, applyOnClose=True, style={"height": 420}, ) ``` - `readonly=True` makes the complete grid read-only. - A column-level `readonly=True` locks only that column. - `range=True` enables multi-cell selection. - `useClipboard=True` enables the built-in copy/paste behavior. - `rangeFill` requires range selection. References: [Editing](https://rv-grid.com/guide/editing), [Clipboard](https://rv-grid.com/guide/clipboard), [`ClipboardConfig`](https://rv-grid.com/guide/types/Interface.ClipboardConfig), and [Selection API](https://rv-grid.com/guide/api/selectionFocus). ### Filtering and sorting Enable the filter plugin at grid level, then opt columns into a filter family: ```python RevoGrid( filter={ "collection": { "status": {"type": "eq", "value": "Open"}, } }, sorting={ "columns": [ {"prop": "amount", "order": "desc"}, ], "additive": False, }, columns=[ {"prop": "status", "name": "Status", "filter": "string"}, { "prop": "amount", "name": "Amount", "filter": "number", "sortable": True, }, ], source=rows, style={"height": 420}, ) ``` Custom filter functions and custom sorting comparators are JavaScript functions, so they are not supported through Python in v1. References: [Filtering](https://rv-grid.com/guide/filters), [`ColumnFilterConfig`](https://rv-grid.com/guide/types/Interface.ColumnFilterConfig), [Sorting](https://rv-grid.com/guide/sorting), and [`SortingConfig`](https://rv-grid.com/guide/types/TypeAlias.SortingConfig). ### Row grouping ```python RevoGrid( grouping={ "props": ["region", "team"], "expandedAll": True, "preserveGroupingOnUpdate": True, }, columns=columns, source=rows, style={"height": 420}, ) ``` `groupLabelTemplate` and `getGroupValue` are functions and cannot cross the Python boundary. The plain-object grouping options work. References: [Row Grouping](https://rv-grid.com/guide/row/grouping) and [`GroupingOptions`](https://rv-grid.com/guide/types/TypeAlias.GroupingOptions). ### Sizing, pinned rows, and column movement ```python RevoGrid( colSize=120, rowSize=34, rowHeaders={"size": 56}, resize=True, autoSizeColumn=True, stretch="last", canMoveColumns=True, pinnedTopSource=[{"name": "Current selection"}], pinnedBottomSource=[{"name": "Total"}], columns=columns, source=rows, style={"height": 500}, ) ``` References: [Grid Size](https://rv-grid.com/guide/grid.size), [Column Resize](https://rv-grid.com/guide/column/resize), [Column Autosize](https://rv-grid.com/guide/column/autosize), [Column Stretch](https://rv-grid.com/guide/column/stretch), [Column Ordering](https://rv-grid.com/guide/column/order), [Row Headers](https://rv-grid.com/guide/row/headers), and [Pinned Rows](https://rv-grid.com/guide/row/pin). ### Themes, RTL, accessibility, and virtualization ```python RevoGrid( theme="compact", rtl=False, accessible=True, frameSize=1, disableVirtualX=False, disableVirtualY=False, columns=columns, source=rows, style={"height": 420}, ) ``` Virtual rendering is enabled by default. Leave it enabled for large sources. `virtualX` can restrict which column dimensions use X-axis virtualization; its values come from [`DimensionCols`](https://rv-grid.com/guide/types/TypeAlias.DimensionCols). References: [Themes](https://rv-grid.com/guide/theme), [RTL](https://rv-grid.com/guide/rtl), [Accessibility](https://rv-grid.com/guide/wcag), [Performance and Virtualization](https://rv-grid.com/guide/performance), and [Viewports](https://rv-grid.com/guide/viewports). --- # Dash Callbacks and Events Source: https://rv-grid.com/guide/dash/callbacks-and-events Description: Handle RevoGrid events with generated Plotly Dash callback properties. # Callbacks and events ### Generated callback properties Every public RevoGrid event discovered in Stencil compiler metadata is generated as a same-name Dash input property. The most common events are active by default: | Dash property | When it updates | Typical `detail` | Core reference | | --- | --- | --- | --- | | `afteredit` | A cell or selected range is changed | Compact cell delta, or range data and ranges | [`AfterEditEvent`](https://rv-grid.com/guide/types/TypeAlias.AfterEditEvent) | | `afterfocus` | Focus rendering completes | Focused cell/range information | [`FocusAfterRenderEvent`](https://rv-grid.com/guide/types/Interface.FocusAfterRenderEvent) | | `headerclick` | A column header is clicked | JSON-safe column definition | [`ColumnRegular`](https://rv-grid.com/guide/types/Interface.ColumnRegular) | | `roworderchanged` | A row reorder is requested | `from`, `to` | [Row Drag and Drop](https://rv-grid.com/guide/row/order) | | `aftersortingapply` | Sorting finishes | Final sorting state and affected row types | [`AfterSortingApplyEvent`](https://rv-grid.com/guide/types/TypeAlias.AfterSortingApplyEvent) | | `beforefilterapply` | Filtering is about to apply | Filter `collection` | [Filtering events](https://rv-grid.com/guide/filters#event-hooks) | | `aftercolumnresize` | Column resizing finishes | Resized columns keyed by index | [Column Resize](https://rv-grid.com/guide/column/resize) | All callback values use the same envelope: ```json { "name": "afteredit", "detail": { "rowIndex": 0, "colIndex": 2, "prop": "amount", "val": 140, "type": "rgRow", "colType": "rgCol" }, "timestamp": 1784980000000, "sequence": 1 } ``` - `name` is the lowercase RevoGrid DOM event name. - `detail` contains the JSON-safe event payload. - `timestamp` is the browser time in Unix milliseconds. - `sequence` increases for every emitted bridge event, so two identical consecutive event payloads still trigger Dash. For a single-cell edit, `afteredit.detail` keeps only `rowIndex`, `colIndex`, `prop`, `val` or `value`, `type`, and `colType`. For a range edit, it keeps `data`, `newRange`, `oldRange`, and `type`. Grid-owned models and collections are intentionally removed. ### Observe several events ```python from dash import Input, Output, callback, ctx import json @callback( Output("grid-events", "children"), Input("orders-grid", "afteredit"), Input("orders-grid", "afterfocus"), Input("orders-grid", "aftersortingapply"), prevent_initial_call=True, ) def show_grid_event(afteredit, afterfocus, aftersorting): property_name = ctx.triggered[0]["prop_id"].rsplit(".", 1)[1] event = { "afteredit": afteredit, "afterfocus": afterfocus, "aftersortingapply": aftersorting, }[property_name] return json.dumps(event, indent=2) ``` For callbacks with several inputs, `dash.ctx` identifies exactly which property triggered the callback. ### Subscribe to any other RevoGrid event Use `eventListeners` to activate generated event properties that are not active by default. Their latest payload is published through both the same-name property and the backwards-compatible `eventData` property: ```python grid = RevoGrid( id="orders-grid", eventListeners=[ "aftergridinit", "filterconfigchanged", "sortingconfigchanged", ], columns=columns, source=rows, style={"height": 420}, ) @callback( Output("generic-event", "children"), Input("orders-grid", "eventData"), prevent_initial_call=True, ) def show_generic_event(event): return f'{event["sequence"]}: {event["name"]}' ``` Names are deduplicated and listeners are updated when `eventListeners` changes. Default event names do not need to be listed because their generated Dash properties already receive them. Runtime plugin events absent from Stencil metadata continue to update `eventData` only. Do not subscribe to high-frequency events such as `viewportscroll` unless a server round trip for every event is intentional. Browse the [complete Core events table](https://rv-grid.com/guide/api/events) and [event lifecycle guide](https://rv-grid.com/guide/events-guide) to choose names and understand event order. ### JSON-safe event serialization The bridge serializes event details before calling Dash `setProps`: - strings, finite numbers, booleans, `null`, arrays, and plain objects remain; - JavaScript `Date` values become ISO strings; - non-finite numbers, cycles, DOM nodes, and class instances become `null`; - unsupported object fields such as functions, symbols, and `undefined` are omitted; - unsupported array entries become `null`. This protects callbacks from DOM and grid-internal objects that Dash cannot transport. --- # Dash Edit Synchronization Source: https://rv-grid.com/guide/dash/edit-synchronization Description: Choose compact edit events or full source synchronization for RevoGrid in Plotly Dash. # Edit synchronization Choose the source ownership model deliberately. ### Recommended default: compact edit deltas `syncSourceOnEdit=False` is the default. RevoGrid applies the edit in the browser and sends only `afteredit` to Python: ```text edit in browser -> compact afteredit envelope -> Dash callback ``` This is the right default for large sources, autosave APIs, audit logs, patch queues, and applications that can persist one changed field at a time. ```python @callback( Output("save-status", "children"), Input("orders-grid", "afteredit"), prevent_initial_call=True, ) def persist_edit(event): detail = event["detail"] if "prop" not in detail: return "A range edit was received" save_cell_change( row_index=detail["rowIndex"], field=detail["prop"], value=detail["val"], ) return f'Saved row {detail["rowIndex"]}' ``` `save_cell_change` represents the application's persistence layer. In a real multi-user application, include a stable row identifier in the source and map the reported `rowIndex` to that identifier. ### Opt in to complete source synchronization Set `syncSourceOnEdit=True` when a Dash callback genuinely needs the complete edited source: ```python RevoGrid( id="orders-grid", syncSourceOnEdit=True, columns=columns, source=rows, style={"height": 420}, ) @callback( Output("row-count", "children"), Input("orders-grid", "source"), prevent_initial_call=True, ) def receive_complete_source(source): return f"{len(source)} rows received" ``` After each edit, the bridge creates a JSON-safe snapshot and updates `source` together with `afteredit`. It also recognizes the immediate Dash echo of that snapshot and does not assign it back to the grid a second time. This mode costs memory, serialization time, and network bandwidth proportional to the complete dataset. Leave it disabled when a compact delta is sufficient. --- # Dash Property Reference Source: https://rv-grid.com/guide/dash/property-reference Description: Review supported RevoGrid properties, Python boundary limitations, and troubleshooting for Plotly Dash. # Complete property reference The table below is the complete public property surface of `dash_datagrid.RevoGrid`. ### Dash host and bridge properties | Property | Python shape | Purpose | | ---------------------------- | ------------------------ | ------------------------------------------------------------------------ | | `id` | `str` or Dash pattern ID | Component identifier used by callbacks | | `className` | `str` | CSS class on the Dash host element | | `style` | `dict` | Inline host style; normally include a `height` | | Every public Core event name | `dict` | Latest JSON-safe envelope; generated automatically from Stencil metadata | | `eventListeners` | `list[str]` | Additional generated or runtime event names to activate | | `eventData` | `dict` | Latest generic event envelope | | `syncSourceOnEdit` | `bool`, default `False` | Also update the complete Dash `source` after edits | ### Core data and schema properties | Property | Python shape | Purpose | Reference | | -------------------- | ------------ | -------------------------------------- | ---------------------------------------------------------------------- | | `columns` | `list[dict]` | Regular and grouped column definitions | [Columns](https://rv-grid.com/guide/column) | | `source` | `list[dict]` | Main row source | [Rows](https://rv-grid.com/guide/row) | | `pinnedTopSource` | `list[dict]` | Rows in the top pinned viewport | [Pinned rows](https://rv-grid.com/guide/row/pin) | | `pinnedBottomSource` | `list[dict]` | Rows in the bottom pinned viewport | [Pinned rows](https://rv-grid.com/guide/row/pin) | | `columnTypes` | `dict` | Named JSON-safe column presets | [Column types](https://rv-grid.com/guide/column/types) | | `rowDefinitions` | `list[dict]` | Per-row sizes by type and index | [`RowDefinition`](https://rv-grid.com/guide/types/TypeAlias.RowDefinition) | | `additionalData` | `dict` | Extra plain JSON context | [Advanced configuration](https://rv-grid.com/guide/advanced-configuration#additionaldata) | ### Core layout and interaction properties | Property | Python shape | Purpose | Reference | | ---------------- | ---------------- | -------------------------------------------- | ---------------------------------------------------------------- | | `rowHeaders` | `bool` or `dict` | Row numbers or JSON-safe row-header options | [Row headers](https://rv-grid.com/guide/row/headers) | | `colSize` | number | Default column width | [Grid size](https://rv-grid.com/guide/grid.size) | | `rowSize` | number | Default row height | [Row height](https://rv-grid.com/guide/row/height) | | `rowClass` | `str` | Source field containing the row CSS class | [Rows](https://rv-grid.com/guide/row#row-class-binding) | | `resize` | `bool` | Allow column resizing | [Column resize](https://rv-grid.com/guide/column/resize) | | `autoSizeColumn` | `bool` or `dict` | Enable/configure automatic column sizing | [Column autosize](https://rv-grid.com/guide/column/autosize) | | `stretch` | `bool` or `str` | Fill remaining horizontal space | [Column stretch](https://rv-grid.com/guide/column/stretch) | | `readonly` | `bool` | Make the complete grid read-only | [Editing](https://rv-grid.com/guide/editing) | | `applyOnClose` | `bool` | Apply an editor value when the editor closes | [Editing](https://rv-grid.com/guide/editing) | | `range` | `bool` | Enable cell range selection | [Selection API](https://rv-grid.com/guide/api/selectionFocus) | | `useClipboard` | `bool` or `dict` | Enable/configure clipboard behavior | [Clipboard](https://rv-grid.com/guide/clipboard) | | `canFocus` | `bool` | Allow grid cell focus | [Advanced configuration](https://rv-grid.com/guide/advanced-configuration#canfocus) | | `canMoveColumns` | `bool` | Enable column reordering | [Column ordering](https://rv-grid.com/guide/column/order) | | `canDrag` | `bool` | Allow the native drag-and-drop path | [Row ordering](https://rv-grid.com/guide/row/order) | ### Core data feature properties | Property | Python shape | Purpose | Reference | | ------------- | ---------------- | ------------------------------------ | ------------------------------------------------------- | | `filter` | `bool` or `dict` | Enable/configure built-in filtering | [Filtering](https://rv-grid.com/guide/filters) | | `sorting` | `dict` | Apply external sorting configuration | [Sorting](https://rv-grid.com/guide/sorting) | | `grouping` | `dict` | Configure Core row grouping | [Row grouping](https://rv-grid.com/guide/row/grouping) | | `trimmedRows` | `dict` | Hide physical main-row indexes | [Rows and trimming](https://rv-grid.com/guide/row#managing-row-visibility) | | `exporting` | `bool` | Enable the Core export plugin | [Export plugin](https://rv-grid.com/guide/export.plugin) | ### Core rendering and platform properties | Property | Python shape | Purpose | Reference | | ---------------------------- | ------------ | ------------------------------------------------------------------ | ------------------------------------------------- | | `theme` | `str` | RevoGrid theme name | [Themes](https://rv-grid.com/guide/theme) | | `themeDefinitions` | `list[dict]` | Per-grid custom theme definitions | [Themes](https://rv-grid.com/guide/theme#typed-reusable-themes) | | `accessible` | `bool` | Enable accessibility behavior | [Accessibility](https://rv-grid.com/guide/wcag) | | `rtl` | `bool` | Use right-to-left layout | [RTL](https://rv-grid.com/guide/rtl) | | `frameSize` | number | Off-screen virtualization buffer | [Performance](https://rv-grid.com/guide/performance#framesize) | | `disableVirtualX` | `bool` | Disable column virtualization | [Performance](https://rv-grid.com/guide/performance#disablevirtualx) | | `disableVirtualY` | `bool` | Disable row virtualization | [Performance](https://rv-grid.com/guide/performance#disablevirtualy) | | `virtualX` | `list[str]` | Column dimensions using X virtualization | [Viewports](https://rv-grid.com/guide/viewports) | | `noHorizontalScrollTransfer` | `bool` | Do not mirror horizontal scroll between viewport sections | [RevoGrid API](https://rv-grid.com/guide/api/revoGrid) | | `hideAttribution` | `bool` | Hide attribution; use only with the required RevoGrid subscription | [Attribution](https://rv-grid.com/guide/attribution) | For exact Core defaults and TypeScript types, use the [RevoGrid component API](https://rv-grid.com/guide/api/revoGrid). The Python signature and docstring are generated with the package, so `help(RevoGrid)` also lists every Dash property: ```python from dash_datagrid import RevoGrid help(RevoGrid) ``` ## Python boundary limitations ### Excluded grid properties The wrapper intentionally excludes properties whose values require JavaScript functions, classes, promises, or virtual DOM nodes: | Excluded Core property | Why it is excluded | | ---------------------- | -------------------------------------------- | | `editors` | Values are editor constructors/classes | | `plugins` | Values are plugin classes | | `focusTemplate` | Value is a render function | | `jobsBeforeRender` | Values are browser promises | | `registerVNode` | Values are virtual nodes or render functions | Function-valued members nested inside otherwise supported objects are also unsupported. Examples include custom cell/header templates, custom editor constructors, custom comparison or parser functions, custom filter functions, and custom grouping renderers. ### `before*` events cannot cancel server-side Core `before*` DOM events may be cancelable in JavaScript because a browser listener can call `preventDefault()` synchronously. A Python Dash callback runs after a network round trip, so `beforefilterapply` and generic `before*` events are notifications only. They cannot prevent or rewrite the browser action. ### Imperative methods The Core API includes methods for selection, scrolling, data access, export, and targeted updates. Those methods are documented for JavaScript consumers but are not callable through `dash_datagrid.RevoGrid` in v1. Use declarative Dash output properties for Python-driven changes. ## Troubleshooting ### The grid has no visible height Give the component host an explicit height: ```python RevoGrid(..., style={"height": "60vh", "minHeight": 320}) ``` ### A prop is not JSON serializable Normalize DataFrame values, NumPy values, `Decimal`, timestamps, UUIDs, and custom Python objects before assigning them. Dash must serialize props before they reach RevoGrid. ### A custom renderer, editor, comparator, or filter does not work Those APIs require JavaScript functions. They are part of the Core JavaScript API but outside the v1 Python boundary. ### A `before*` callback did not prevent an action Python callbacks cannot synchronously cancel browser events. Observe the resulting event, or implement the behavior declaratively with a new prop value. ### Editing a large source causes large callback requests Leave `syncSourceOnEdit=False` and consume the compact `afteredit` delta. Full source synchronization is opt-in. ### A generic event does not update `eventData` Use the lowercase event name shown in the [Core events table](https://rv-grid.com/guide/api/events). Auto-discovered events update their named Dash property and `eventData`; runtime-only plugin events update `eventData`. --- # Dash Core API Reference Source: https://rv-grid.com/guide/dash/core-api-reference Description: Find the RevoGrid Core API documentation that applies to the Plotly Dash wrapper. # RevoGrid API reference These pages are the source of truth behind the Dash wrapper: | Area | Documentation | | --- | --- | | Complete component properties, events, and methods | [RevoGrid API](https://rv-grid.com/guide/api/revoGrid) | | Complete event name and payload table | [Events API](https://rv-grid.com/guide/api/events) | | Event ordering and lifecycle diagrams | [Event Patterns](https://rv-grid.com/guide/events-guide) | | Generated TypeScript type index | [Type reference](https://rv-grid.com/guide/types/README) | | Columns and column schema | [Columns](https://rv-grid.com/guide/column), [`ColumnRegular`](https://rv-grid.com/guide/types/Interface.ColumnRegular), [`ColumnGrouping`](https://rv-grid.com/guide/types/Interface.ColumnGrouping) | | Rows, row headers, row sizes, pinning, ordering | [Rows](https://rv-grid.com/guide/row), [Row Headers](https://rv-grid.com/guide/row/headers), [Row Height](https://rv-grid.com/guide/row/height), [Pinned Rows](https://rv-grid.com/guide/row/pin), [Row Order](https://rv-grid.com/guide/row/order) | | Editing, selection, clipboard | [Editing](https://rv-grid.com/guide/editing), [Selection API](https://rv-grid.com/guide/api/selectionFocus), [Clipboard](https://rv-grid.com/guide/clipboard), [Clipboard API](https://rv-grid.com/guide/api/clipboard) | | Filtering, sorting, grouping | [Filtering](https://rv-grid.com/guide/filters), [Sorting](https://rv-grid.com/guide/sorting), [Row Grouping](https://rv-grid.com/guide/row/grouping) | | Sizing and column layout | [Grid Size](https://rv-grid.com/guide/grid.size), [Autosize](https://rv-grid.com/guide/column/autosize), [Resize](https://rv-grid.com/guide/column/resize), [Stretch](https://rv-grid.com/guide/column/stretch), [Pin Columns](https://rv-grid.com/guide/column/pin), [Column Order](https://rv-grid.com/guide/column/order) | | Source ownership and remote data | [Data Sync](https://rv-grid.com/guide/data-sync), [Server-side Data](https://rv-grid.com/guide/server-side-data), [Real-time Updates](https://rv-grid.com/guide/realtime-updates) | | Virtualization and indexes | [Performance](https://rv-grid.com/guide/performance), [Viewports](https://rv-grid.com/guide/viewports) | | Themes, accessibility, RTL | [Themes](https://rv-grid.com/guide/theme), [Accessibility](https://rv-grid.com/guide/wcag), [RTL](https://rv-grid.com/guide/rtl) | | Export | [Export Plugin](https://rv-grid.com/guide/export.plugin), [Excel Export](https://rv-grid.com/guide/data-grid-export-excel), [PDF Export](https://rv-grid.com/guide/pdf-export) | The Core API pages also document browser-only methods and function-valued types. Use the [complete property reference](https://rv-grid.com/guide/dash/property-reference) and [Python boundary limitations](https://rv-grid.com/guide/dash/property-reference#python-boundary-limitations) on this page to determine which parts are available in Dash. --- # Vue 3 Data Grid Source: https://rv-grid.com/guide/vue3 Description: Learn how to use RevoGrid in Vue 3 with Composition API or Options API, pass columns and source data, access instance methods, and build custom renderers. RevoGrid fits naturally into Vue 3 applications when you need a fast grid with native component integrations. You can use it from either the Composition API or the Options API, and still rely on the same core RevoGrid methods and events. ::: info This guide assumes your Vue project already exists. If not, start with the official [Vue quick start](https://vuejs.org/guide/quick-start). ::: ## Install your Vue Data Grid Install [RevoGrid for Vue](https://github.com/revolist/vue3-datagrid) using the following command: ::: code-group ```npm npm i @revolist/vue3-datagrid ``` ```pnpm pnpm add @revolist/vue3-datagrid ``` ```yarn yarn add @revolist/vue3-datagrid ``` ```bun bun add @revolist/vue3-datagrid ``` ::: ## Composition API setup ```vue ``` ## Options API setup ```vue ``` ## Passing `columns` and `source` The most common Vue pattern is: - keep `columns` in component state - pass `source` as reactive data - use grid methods when you need imperative actions like scrolling, focusing, or opening an editor # Get Started with Vue 3 Data Grid Demo - Options API
::: details Source code [Git](https://github.com/revolist/revogrid-docs/tree/main/demo/vue/vue.sample.options.example.vue) [Codesandbox](https://codesandbox.io/p/sandbox/rg-start-vue-3-options-ap-8mlqjx) ::: code-group <<< @/demo/vue/vue.sample.options.example.vue ::: ## Accessing grid instance methods To call a method on the underlying grid, use the wrapped Web Component instance: ```js // ✅ Correct myComponentRef.value.$el.someMethod(); // ❌ Incorrect myComponentRef.value.someMethod(); ``` This matters for methods like `setCellEdit`, `scrollToRow`, `setCellsFocus`, and `getVisibleSource`. ## Custom renderers and editors Use these guides for framework-native customization: - [Vue 3 Cell Template](https://rv-grid.com/guide/vue3/renderer) - [Vue 3 Cell Editor](https://rv-grid.com/guide/vue3/editor) ## Event handling For application workflows, the most useful events are: - `beforeedit` - `afteredit` - `beforefilterapply` - `beforecellfocus` ## SSR and client-only behavior Like the core Web Component, RevoGrid depends on browser APIs. If you use Vue in an SSR setup, render the grid on the client side or guard the component load accordingly. ## Related guides - [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control) - [Advanced Configuration](https://rv-grid.com/guide/advanced-configuration) - [Grid Performance and Virtualization](https://rv-grid.com/guide/performance) --- # Vue Data Grid Cell Template Source: https://rv-grid.com/guide/vue3/renderer Description: Learn about cell template rendering for Vue 3 Data Grid, enabling smooth integration of custom Vue components within grid cells. RevoGrid provide a way to render native components inside of cells. ::: warning If you are aiming for the faster render we are recommending to stick with native VNode render. ::: ::: tip Check [ColumnDataSchemaModel](https://rv-grid.com/guide/types/TypeAlias.ColumnDataSchemaModel) for mode information about input types. ::: ## Vue 3 - Native Cell Component (Composition API)
::: details Source code [Git](https://github.com/revolist/revogrid-docs/tree/main/demo/vue/vue.cell.composition.example.vue) [Codesandbox](https://codesandbox.io/p/sandbox/rg-cell-vue-3-composition-api-cvv97n) ::: code-group <<< @/demo/vue/vue.cell.composition.example.vue <<< @/demo/vue/vue.cell.composition.example-cell.vue ::: ## App ```vue // vue3.app-template.example.vue ``` ## Cell Template ```vue // vue3.cell-template.example.vue ``` ## Why Use Custom Cell Rendering? RevoGrid’s native cell rendering enables you to: - **Embed Components**: Render complex or interactive UI elements inside grid cells, such as buttons, images, input fields, or custom widgets. - **Dynamic Content**: Customize each cell’s content based on the data it represents, such as formatting or conditional rendering. - **Interactivity**: Make cells interactive with event listeners and component lifecycle methods, improving the overall user experience. --- # Vue Data Grid Editor Source: https://rv-grid.com/guide/vue3/editor Description: Discover how to utilize Vue 3 Data Grid for native editor rendering, enabling seamless in-cell editing using Vue components. RevoGrid provides a way to render native components as editor. ::: tip You can access close and save callbacks in properties. Check [editor](https://rv-grid.com/guide/cell/editor) and `EditorCtr` type for more. ::: # Vue 3 Data Grid Cell Editor component (Composition API)
::: details Source code [Git](https://github.com/revolist/revogrid-docs/tree/main/demo/vue/vue.editor.composition.example.vue) [Codesandbox](https://codesandbox.io/p/sandbox/rg-editor-vue-3-composition-api-sl8vvw) ::: code-group <<< @/demo/vue/vue.editor.composition.example.vue <<< @/demo/vue/vue.editor.composition.example-editor.vue ::: ## Data Grid App ```vue // vue.editor.composition.example.vue ``` ## Data Grid Editor Component ```vue // vue.editor.composition.example-editor.vue ``` --- # Svelte Data Grid Source: https://rv-grid.com/guide/svelte Description: Build fast, scalable Svelte Data Grid with support for virtual rows and columns.
# Svelte Data Grid Svelte logo
## Svelte Data Grid Demo Use this Svelte demo to embed RevoGrid in a Svelte application with virtual rows, virtual columns, and editable data grid behavior. [![Edit RG Start (Svelte)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/devbox/rg-start-svelte-k7xdsh?embed=1&file=%2Fsrc%2Froutes%2F%2Bpage.svelte) ::: warning We have updated our latest version to support **Svelte 5** following its official release. 🎉 Read more about the announcement here: [Svelte 5 is Alive](https://svelte.dev/blog/svelte-5-is-alive). If you want to continue using **Svelte 4**, please switch to the [svelte-4](https://github.com/revolist/svelte-datagrid/tree/svelte-4) branch or use version prior to 4.11.0. ::: RevoGrid provide special wrapper based on [stenciljs svelte adapter](https://www.npmjs.com/package/@stencil/svelte-output-target). Just import it to your project and it can be used as part of svelte system. ## Install your Svelte Data Grid Install RevoGrid for Svelte using the following command: ::: code-group ```npm npm install @revolist/svelte-datagrid ``` ```pnpm pnpm add @revolist/svelte-datagrid ``` ```yarn yarn add @revolist/svelte-datagrid ``` ```bun bun add @revolist/svelte-datagrid ``` ## Example <<< @/demo/svelte/svelte.sample.svelte ## SvelteKit ::: warning SSR is not compatible with RevoGrid out of the box because it depends on the browser environment. There is no documentation on hybrid projects with server-side rendering (SSR) for SvelteKit at this time. This is going to be added in the future. ::: Here are two approaches to use RevoGrid in a SvelteKit project: ### Option 1: Disable SSR You can disable SSR for the entire page where RevoGrid is used. This ensures the page is rendered only on the client. Add a `+page.js` (For JavaScript Projects) or `+page.ts` (For TypeScript Projects) file in the same directory as your `+page.svelte`: ```typescript // +page.js or +page.ts export const ssr = false; ``` With this setup, your +page.svelte can directly use RevoGrid: ```svelte ``` ### Option 2: Use CSR (Client-Side Rendering) If you don’t want to disable SSR for the entire page, you can render RevoGrid only in the browser using CSR loading techniques. #### CSR: Conditional Rendering Based on the Browser Use the browser variable from SvelteKit to ensure RevoGrid is only rendered on the client side: ```svelte {#if browser} {:else}

RevoGrid is not available during server-side rendering.

{/if} ``` #### CSR: Lazy-Loading You can dynamically import RevoGrid using Svelte’s onMount lifecycle method. This ensures the library is only loaded after the page is mounted in the browser: ```svelte {#if RevoGrid} {:else}

Loading RevoGrid...

{/if} ``` Check out our repo for example: [SvelteKit](https://github.com/revolist/revogrid-svelte-kit) When to Use These Options? - Disabling SSR for the Page: Use this if the entire page depends on RevoGrid and SSR isn’t necessary. - Client-Side Rendering (CSR) for RevoGrid: Use this if you need other parts of the page to be server-rendered but still want to use RevoGrid in the browser. With these methods, you can successfully integrate RevoGrid into your SvelteKit project while handling its lack of SSR compatibility. ## Related guides - [Programmatic Grid Control](https://rv-grid.com/guide/programmatic-control) - [Grid Performance and Virtualization](https://rv-grid.com/guide/performance) - [Event Patterns and Lifecycles](https://rv-grid.com/guide/events-guide) --- # Svelte Data Grid Cell Template Source: https://rv-grid.com/guide/svelte/renderer Description: Render native Svelte components inside RevoGrid cells with the Svelte Data Grid wrapper. RevoGrid provide a way to render native components inside of cells. ::: warning If you are aiming for the faster render we are recommending to stick with native VNode render. ::: ::: tip Check [ColumnDataSchemaModel](https://rv-grid.com/guide/types/TypeAlias.ColumnDataSchemaModel) for mode information about input types. ::: Use `Template(Component)` from `@revolist/svelte-datagrid` to render a Svelte component inside a `cellTemplate`. ::: tip `Template(Component)` is explicit by design. Native RevoGrid templates like `cellTemplate(h, props)` are still supported, and compiled Svelte components are also functions at runtime, so raw `cellTemplate: Component` is not auto-detected. ::: ## Basic Setup ```svelte ``` ## Cell Component ```svelte ``` The Svelte component receives flat cell props such as `value`, `model`, `prop`, `rowIndex`, `colIndex`, `column`, `data`, `providers`, and `addition`. ## Why Use Custom Cell Rendering? RevoGrid’s native cell rendering enables you to: - **Embed Components**: Render complex or interactive UI elements inside grid cells, such as buttons, images, input fields, or custom widgets. - **Dynamic Content**: Customize each cell’s content based on the data it represents, such as formatting or conditional rendering. - **Interactivity**: Make cells interactive with event listeners and component lifecycle methods, improving the overall user experience. --- # Svelte Data Grid Editor Source: https://rv-grid.com/guide/svelte/editor Description: Build custom RevoGrid editors with native Svelte components. RevoGrid provides a way to render native components as editor. ::: tip You can access close and save callbacks in properties. Check [editor](https://rv-grid.com/guide/cell/editor) and `EditorCtr` type for more. ::: Use `Editor(Component)` from `@revolist/svelte-datagrid` to register a Svelte component as a custom editor. ## Basic Setup ```svelte ``` ## Editor Component ```svelte ``` The editor component receives flat props from `EditorType`, including the current edit-cell data plus: - `column`: the column data schema model. - `save(value, preventFocus?)`: saves the value and closes the editor. - `close(focusNext?)`: closes the editor without saving. If the editor should participate in autosave-on-close, export `getValue()` from the Svelte component. ## Why Use Custom Editors? With native editor rendering, you can: - **Customize the Editing Experience**: Use any React component as a custom editor, providing a tailored user interface for editing data directly in the grid. - **Build Complex Editors**: Embed interactive elements such as date pickers, dropdowns, or custom forms inside cells, which would be impossible with simple input fields alone. - **Improve Usability**: Create inline editors that match your application’s UI, improving consistency and enhancing the overall user experience. --- # Svelte Tree Data Grid Source: https://rv-grid.com/guide/svelte/tree Description: Build a Svelte tree data grid with the free RevoGrid core tree pattern, then use RevoGrid Pro TreeDataPlugin for expandable hierarchy controls and sticky parent rows. Svelte can use the free/core tree pattern with the same RevoGrid Web Component API: flatten your hierarchy, keep a `level` field, and render indentation in a cell template. ::: info The shared live core tree demo is currently published for TypeScript, React, Vue 3, and Angular. Svelte uses the same flat `source` and cell-template approach. ::: Tree-like rows do not require Pro when your application only needs a visual hierarchy. The free/core approach is to flatten parent-child records into display order, add a `level` field, and render indentation in a cell template. This keeps RevoGrid simple: the grid receives a normal `source` array, virtualization still works, and your application owns the hierarchy transformation. ## Tree model Start with records that have an ID and a parent ID: ```ts const inputData = [ { id: 4, parentId: 0, name: 'Antoni father for 2' }, { id: 5, parentId: 4, name: 'Odin' }, { id: 6, parentId: 4, name: 'John' }, { id: 1, parentId: 0, name: 'Mary mother for 2' }, { id: 2, parentId: 1, name: 'Howard has also 2' }, ]; ``` Convert that data into a flat display list before assigning it to the grid: ```ts function buildTreeData(rows: typeof inputData, rootParentId = 0) { const childrenByParent = new Map(); for (const row of rows) { const children = childrenByParent.get(row.parentId) ?? []; children.push(row); childrenByParent.set(row.parentId, children); } const result: Array<(typeof inputData)[number] & { level: number }> = []; function appendChildren(parentId: number, level = 0) { for (const child of childrenByParent.get(parentId) ?? []) { result.push({ ...child, level }); appendChildren(child.id, level + 1); } } appendChildren(rootParentId); return result; } ``` ## Indented cell template The core demo uses a normal cell template to show hierarchy depth: ```ts const columns = [ { prop: 'name', name: 'Tree', size: 300, cellTemplate(h, { value, model }) { return h( 'div', { style: { marginLeft: `${(model?.level ?? 0) * 30}px`, }, }, value || '', ); }, }, { prop: 'level', readonly: true, }, ]; ``` Use the core approach when the hierarchy is read-only or mostly decorative: category outlines, simple nested lists, document sections, or a tree table where your app handles all expand/collapse logic outside the grid. ## Core limits The free/core pattern is intentionally lightweight. It does not add built-in expand/collapse controls, automatic parent-child visibility, tree-aware drag-and-drop, sticky parent rows, or parent/descendant row selection behavior. Those behaviors belong in the Pro Tree Data plugin. ## Svelte notes - Keep the input hierarchy and flattened `treeData` in component state or a store. - Reassign `treeData` when the hierarchy changes. - In SvelteKit, render RevoGrid only on the client, as described in the main Svelte guide. ```svelte ``` ## Pro Tree Data RevoGrid Pro adds a dedicated `TreeDataPlugin` for advanced data grid tree structures. It keeps the original `source` flat, computes hierarchy metadata internally, and renders tree controls in the column marked with `tree: true`. ::: info RevoGrid Pro Use the Pro plugin when hierarchy is not just indentation: users need expand/collapse controls, persistent expansion state, filtering and sorting with hierarchy awareness, row selection across descendants, drag-and-drop reparenting, or sticky parent rows while scrolling long branches. ::: ### Pro data model The Pro model also starts from stable IDs and parent IDs: ```ts type TeamRow = { id: string; parentId: string | null; name: string; role: string; budget: number; }; const source: TeamRow[] = [ { id: 'eng', parentId: null, name: 'Engineering', role: 'Department', budget: 850000 }, { id: 'platform', parentId: 'eng', name: 'Platform', role: 'Team', budget: 320000 }, { id: 'api', parentId: 'platform', name: 'API', role: 'Squad', budget: 140000 }, { id: 'design', parentId: null, name: 'Design', role: 'Department', budget: 260000 }, ]; ``` Unlike the core example, you do not add `level` yourself. The plugin derives level, visibility, expanded state, and child metadata from the tree config. ### Pro column and plugins Mark one hierarchy column with `tree: true`, register `TreeDataPlugin`, and pass the `tree` config: ```ts import { TreeDataPlugin, RowOrderPlugin, RowSelectPlugin, StickyCellsPlugin, TREE_EXPAND_ALL_EVENT, TREE_COLLAPSE_ALL_EVENT, } from '@revolist/revogrid-pro'; const columns = [ { prop: 'name', name: 'Team', size: 300, tree: true, sortable: true, rowSelect: true, rowDrag: true, }, { prop: 'role', name: 'Role', size: 160 }, { prop: 'budget', name: 'Budget', size: 140 }, ]; const plugins = [ TreeDataPlugin, RowOrderPlugin, RowSelectPlugin, StickyCellsPlugin, ]; const tree = { idField: 'id', parentIdField: 'parentId', rootParentId: null, expandedRowIds: new Set(['eng']), stickyParents: true, }; ``` Framework wrappers pass these values as props or bindings. Plain TypeScript assigns them to the `revo-grid` element. ### Expand and collapse controls The Pro plugin exposes events for toolbar buttons and external controls: ```ts grid.dispatchEvent(new CustomEvent(TREE_EXPAND_ALL_EVENT)); grid.dispatchEvent(new CustomEvent(TREE_COLLAPSE_ALL_EVENT)); ``` Use `expandAll: true` when every branch should open on first render. Use `expandedRowIds` when you want controlled initial state or persisted expansion. ### Production guidance - Keep IDs stable across refreshes so expanded state survives data updates. - Use `parentId: null` or another explicit `rootParentId` consistently. - Keep only one tree column active; use normal columns for the rest of the row data. - Combine tree data with virtualization for large hierarchies instead of rendering nested DOM lists. - Add `StickyCellsPlugin` only when sticky parent rows are useful for long branches. - Reconcile drag-and-drop changes in your application store before saving to the backend. - Prefer flat server payloads for large trees; they are simpler to page, diff, validate, and persist. ## Related guides - [Advanced Tree Data guide](https://rv-grid.com/guide/tree-data) - [Row Ordering](https://rv-grid.com/guide/row/order) - [Row Selection](https://rv-grid.com/guide/row/selection.pro) - [Filtering](https://rv-grid.com/guide/filters) - [Grid Performance and Virtualization](https://rv-grid.com/guide/performance) --- # Demo Svelte Data Grid Source: https://rv-grid.com/guide/demos/svelte/svelte-datagrid Description: Learn how to integrate RevoGrid with Svelte to build fast, scalable data grids with support for virtual rows and columns. ## Svelte Data Grid Demo Use this Svelte demo to embed RevoGrid in a Svelte application with virtual rows, virtual columns, and editable data grid behavior. [![Edit RG Start (Svelte)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/devbox/rg-start-svelte-k7xdsh?embed=1&file=%2Fsrc%2Froutes%2F%2Bpage.svelte) --- # Stencil Data Grid Source: https://rv-grid.com/guide/stencil Description: Learn how to use Stencil Data Grid to build fast, scalable data applications with support for virtual rows and columns.
# Stencil Data Grid StencilJs logo This page covers the key concepts of RevoGrid - a high-performance, customizable StencilJS Table and StencilJS Data Grid for managing large datasets.
# Stencil Data Grid Demo Use this Stencil demo to add RevoGrid as a Web Component and test the setup in StackBlitz. [Edit RG Start (StencilJs)](https://stackblitz.com/edit/stencil-template-aiden-xadqm4?file=src%2Fcomponents%2Fmy-component%2Fmy-component.tsx) ## What is StencilJS? Stencil aims to eliminate the need for writing components with a specific framework’s API. It achieves this by leveraging standardized web platform APIs compatible with all modern browsers. By using the browser’s low-level component model, which underpins all frameworks, Stencil components can function both within a framework and independently. Integrating web components directly into existing applications can be challenging due to the varying levels of support frameworks have for vanilla web components. For more information about getting started with StencilJS, visit the [official StencilJS documentation](https://stenciljs.com/docs/getting-started). ## Install your React Data Grid Install RevoGrid for React using the following command: ::: code-group ```npm npm i @revolist/react-datagrid ``` ```pnpm pnpm add @revolist/react-datagrid ``` ```yarn yarn add @revolist/react-datagrid ``` ```bun bun add @revolist/react-datagrid ``` ::: ## Usage Create a StencilJS component and import the necessary modules. Define the custom elements and configure your component as follows: <<< @/demo/stencil/stencil.sample.tsx ### Explanation 1. **Import Statements**: Import necessary modules from `@revolist/revogrid` and StencilJS core. 2. **Component Decorator**: Use the `@Component` decorator to define a new Stencil component with the tag name `my-component`. 3. **Column Definition**: Define the columns for the grid using the `ColumnRegular` type. 4. **Data Source**: Define the data source for the grid. 5. **Lifecycle Method**: Use the `componentWillLoad` lifecycle method to initialize the RevoGrid custom elements. 6. **Render Method**: Render the `revo-grid` component with the defined columns and data source, and enable filtering. That's it! Your StencilJS project is now set up to use RevoGrid. --- # StencilJs Getting Started Source: https://rv-grid.com/guide/demos/stencil/stencil.sample Description: Start a Stencil data grid demo with RevoGrid as a Web Component, including an editable StackBlitz example. # Stencil Data Grid Demo Use this Stencil demo to add RevoGrid as a Web Component and test the setup in StackBlitz. [Edit RG Start (StencilJs)](https://stackblitz.com/edit/stencil-template-aiden-xadqm4?file=src%2Fcomponents%2Fmy-component%2Fmy-component.tsx) --- # Vue 2 Data Grid Source: https://rv-grid.com/guide/vue2 Description: Use Vue 2 Data Grid to build fast, scalable data applications with support for virtual rows and columns. This page covers the key concepts of RevoGrid - a high-performance, customizable Vue 2 Table and Vue 2 Data Grid for managing large datasets. # Getting Started - Vue 2 Data Grid [![Edit RG Start (Vue 2)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-start-vue-2-3zl8hd) ## Install your Vue 2 Data Grid Install [RevoGrid for Vue 2](https://www.npmjs.com/package/@revolist/vue-datagrid) using the following command: ::: code-group ```npm npm i @revolist/vue-datagrid ``` ```pnpm pnpm add @revolist/vue-datagrid ``` ```yarn yarn add @revolist/vue-datagrid ``` ```bun bun add @revolist/vue-datagrid ``` ::: ## Vue 2 Data Grid Usage ```vue // App.vue ``` # Getting Started - Vue 2 Data Grid [![Edit RG Start (Vue 2)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-start-vue-2-3zl8hd) ## Check out our Vue Data Grid examples --- # Vue 2 Native Cell Render Support in RevoGrid Source: https://rv-grid.com/guide/vue2/renderer Description: Explore native cell rendering support in RevoGrid for Vue 2, enabling seamless integration of custom Vue components inside grid cells. # Vue 2 Data Grid Cell Template RevoGrid provide a way to render native components inside of cells. ::: warning If you are aiming for the faster render we are recommending to stick with native VNode render. ::: ::: tip Check [ColumnDataSchemaModel](https://rv-grid.com/guide/types/TypeAlias.ColumnDataSchemaModel) for mode information about input types. ::: Create component which you would like to be presented as cell. You can use `props` to access row model object, column property or other props described in `ColumnDataSchemaModel`.
Check [interfaces](https://github.com/revolist/revogrid/blob/master/src/interfaces.d.ts) for mode information about types. # Native Cell Component - Vue 2 Data Grid [![Edit RG Cell (Vue 2)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-cell-vue-2-78q5fl) ## App ```vue // App.vue // App.vue ``` ## Cell template ```vue // Cell.vue ``` ## Why Use Custom Cell Rendering? RevoGrid’s native cell rendering enables you to: - **Embed Components**: Render complex or interactive UI elements inside grid cells, such as buttons, images, input fields, or custom widgets. - **Dynamic Content**: Customize each cell’s content based on the data it represents, such as formatting or conditional rendering. - **Interactivity**: Make cells interactive with event listeners and component lifecycle methods, improving the overall user experience. ## Check out our Vue Data Grid examples --- # Vue 2 Data Grid Editor Source: https://rv-grid.com/guide/vue2/editor Description: Discover how to use Vue 2 for native editor rendering in Vue 2 Data Grid, allowing for custom in-cell editing with Vue components. RevoGrid provides a way to render native components as editor. ::: tip You can access close and save callbacks in properties. Check [editor](https://rv-grid.com/guide/cell/editor) and `EditorCtr` type for more. ::: # Native Editor Component - Vue 2 Data Grid [![Edit RG Editor (Vue 2)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-editor-vue-2-9zr8ng) ## App ```vue // App.vue ``` ## Editor ```vue // Editor.vue ``` ## Check out our Vue Data Grid examples --- # TanStack Integration Source: https://rv-grid.com/guide/tanstack Description: Integrate RevoGrid with TanStack to build fast, scalable data grids with support for virtual rows and columns. # Getting Started with TanStack [TanStack](https://tanstack.com/table/latest/docs/introduction) is a popular framework for building table data layers. However, RevoGrid offers a more comprehensive solution by incorporating all the features of [TanStack](https://tanstack.com/table/latest/docs/introduction), along with advanced rendering, virtual scrolling, and column-level optimizations for superior performance. If you're transitioning from an existing TanStack architecture or want to quickly prototype, this guide will help you integrate [TanStack](https://tanstack.com/table/latest/docs/introduction) with RevoGrid. We strongly recommend using RevoGrid's native features for the best performance. It is specifically designed to handle advanced rendering and optimize every aspect of DOM manipulation, ensuring an efficient experience. RevoGrid operates on the column level, which allows for superior performance, whereas TanStack manages data at the row level. The following example shows how to use TanStack with RevoGrid to create columns, bind data, and manage interactions. ## TanStack Data Grid Demo with RevoGrid Use this demo to compare how TanStack Table data models can be rendered through RevoGrid in Vue and React applications.
::: details Source code [Git](https://github.com/revolist/revogrid-docs/tree/main/demo/vue/DemoTanstack.vue) ::: code-group <<< @/demo/vue/DemoTanstack.vue[Vue example] <<< @/demo/react/react.tanstack.tsx[React example] <<< @/demo/tanstack/utils.ts <<< @/demo/makeData.ts ::: ## Summary Integrating TanStack with RevoGrid allows you to leverage the row-level operations provided by TanStack, while taking advantage of RevoGrid's optimized performance and advanced rendering capabilities, including virtual scrolling and efficient DOM handling. For a smooth migration or quick experimentation, this setup provides a great foundation, but remember, RevoGrid's built-in features are crafted for peak performance and user experience. --- # TanStack Tree Data Grid Source: https://rv-grid.com/guide/tanstack/tree Description: Combine TanStack state management with the free RevoGrid core tree pattern, then use RevoGrid Pro TreeDataPlugin for expandable hierarchy controls and sticky parent rows. TanStack can own query, filter, sorting, and expansion state while RevoGrid renders the virtualized grid surface. Start with the free/core tree pattern by deriving a flat display list from TanStack-managed rows. ::: info Tree rendering is still handled by RevoGrid. TanStack can own the application state around the tree, while RevoGrid receives a flat `source` and renders the cells. ::: Tree-like rows do not require Pro when your application only needs a visual hierarchy. The free/core approach is to flatten parent-child records into display order, add a `level` field, and render indentation in a cell template. This keeps RevoGrid simple: the grid receives a normal `source` array, virtualization still works, and your application owns the hierarchy transformation. ## Tree model Start with records that have an ID and a parent ID: ```ts const inputData = [ { id: 4, parentId: 0, name: 'Antoni father for 2' }, { id: 5, parentId: 4, name: 'Odin' }, { id: 6, parentId: 4, name: 'John' }, { id: 1, parentId: 0, name: 'Mary mother for 2' }, { id: 2, parentId: 1, name: 'Howard has also 2' }, ]; ``` Convert that data into a flat display list before assigning it to the grid: ```ts function buildTreeData(rows: typeof inputData, rootParentId = 0) { const childrenByParent = new Map(); for (const row of rows) { const children = childrenByParent.get(row.parentId) ?? []; children.push(row); childrenByParent.set(row.parentId, children); } const result: Array<(typeof inputData)[number] & { level: number }> = []; function appendChildren(parentId: number, level = 0) { for (const child of childrenByParent.get(parentId) ?? []) { result.push({ ...child, level }); appendChildren(child.id, level + 1); } } appendChildren(rootParentId); return result; } ``` ## Indented cell template The core demo uses a normal cell template to show hierarchy depth: ```ts const columns = [ { prop: 'name', name: 'Tree', size: 300, cellTemplate(h, { value, model }) { return h( 'div', { style: { marginLeft: `${(model?.level ?? 0) * 30}px`, }, }, value || '', ); }, }, { prop: 'level', readonly: true, }, ]; ``` Use the core approach when the hierarchy is read-only or mostly decorative: category outlines, simple nested lists, document sections, or a tree table where your app handles all expand/collapse logic outside the grid. ## Core limits The free/core pattern is intentionally lightweight. It does not add built-in expand/collapse controls, automatic parent-child visibility, tree-aware drag-and-drop, sticky parent rows, or parent/descendant row selection behavior. Those behaviors belong in the Pro Tree Data plugin. ## TanStack notes - Keep row IDs and parent IDs stable in your TanStack data model. - Derive the flattened tree rows from TanStack state. - Persist custom expansion state beside table filters, sorting, or query state if you build free expand/collapse controls. - Pass RevoGrid a flat `source`; do not render nested row components inside the grid. ```ts const treeData = buildTreeData(rowsFromQuery); ``` ## Pro Tree Data RevoGrid Pro adds a dedicated `TreeDataPlugin` for advanced data grid tree structures. It keeps the original `source` flat, computes hierarchy metadata internally, and renders tree controls in the column marked with `tree: true`. ::: info RevoGrid Pro Use the Pro plugin when hierarchy is not just indentation: users need expand/collapse controls, persistent expansion state, filtering and sorting with hierarchy awareness, row selection across descendants, drag-and-drop reparenting, or sticky parent rows while scrolling long branches. ::: ### Pro data model The Pro model also starts from stable IDs and parent IDs: ```ts type TeamRow = { id: string; parentId: string | null; name: string; role: string; budget: number; }; const source: TeamRow[] = [ { id: 'eng', parentId: null, name: 'Engineering', role: 'Department', budget: 850000 }, { id: 'platform', parentId: 'eng', name: 'Platform', role: 'Team', budget: 320000 }, { id: 'api', parentId: 'platform', name: 'API', role: 'Squad', budget: 140000 }, { id: 'design', parentId: null, name: 'Design', role: 'Department', budget: 260000 }, ]; ``` Unlike the core example, you do not add `level` yourself. The plugin derives level, visibility, expanded state, and child metadata from the tree config. ### Pro column and plugins Mark one hierarchy column with `tree: true`, register `TreeDataPlugin`, and pass the `tree` config: ```ts import { TreeDataPlugin, RowOrderPlugin, RowSelectPlugin, StickyCellsPlugin, TREE_EXPAND_ALL_EVENT, TREE_COLLAPSE_ALL_EVENT, } from '@revolist/revogrid-pro'; const columns = [ { prop: 'name', name: 'Team', size: 300, tree: true, sortable: true, rowSelect: true, rowDrag: true, }, { prop: 'role', name: 'Role', size: 160 }, { prop: 'budget', name: 'Budget', size: 140 }, ]; const plugins = [ TreeDataPlugin, RowOrderPlugin, RowSelectPlugin, StickyCellsPlugin, ]; const tree = { idField: 'id', parentIdField: 'parentId', rootParentId: null, expandedRowIds: new Set(['eng']), stickyParents: true, }; ``` Framework wrappers pass these values as props or bindings. Plain TypeScript assigns them to the `revo-grid` element. ### Expand and collapse controls The Pro plugin exposes events for toolbar buttons and external controls: ```ts grid.dispatchEvent(new CustomEvent(TREE_EXPAND_ALL_EVENT)); grid.dispatchEvent(new CustomEvent(TREE_COLLAPSE_ALL_EVENT)); ``` Use `expandAll: true` when every branch should open on first render. Use `expandedRowIds` when you want controlled initial state or persisted expansion. ### Production guidance - Keep IDs stable across refreshes so expanded state survives data updates. - Use `parentId: null` or another explicit `rootParentId` consistently. - Keep only one tree column active; use normal columns for the rest of the row data. - Combine tree data with virtualization for large hierarchies instead of rendering nested DOM lists. - Add `StickyCellsPlugin` only when sticky parent rows are useful for long branches. - Reconcile drag-and-drop changes in your application store before saving to the backend. - Prefer flat server payloads for large trees; they are simpler to page, diff, validate, and persist. ## Related guides - [Advanced Tree Data guide](https://rv-grid.com/guide/tree-data) - [Row Ordering](https://rv-grid.com/guide/row/order) - [Row Selection](https://rv-grid.com/guide/row/selection.pro) - [Filtering](https://rv-grid.com/guide/filters) - [Grid Performance and Virtualization](https://rv-grid.com/guide/performance) --- # TanStack Data Grid Demo with RevoGrid Source: https://rv-grid.com/guide/demos/tanstack Description: Explore a TanStack Table integration demo using RevoGrid for high-performance rendering, large datasets, and Vue and React examples. ## TanStack Data Grid Demo with RevoGrid Use this demo to compare how TanStack Table data models can be rendered through RevoGrid in Vue and React applications.
::: details Source code [Git](https://github.com/revolist/revogrid-docs/tree/main/demo/vue/DemoTanstack.vue) ::: code-group <<< @/demo/vue/DemoTanstack.vue[Vue example] <<< @/demo/react/react.tanstack.tsx[React example] <<< @/demo/tanstack/utils.ts <<< @/demo/makeData.ts ::: --- # Licensing Source: https://rv-grid.com/guide/licensing # Licensing RevoGrid is an open-core, MIT-licensed Data Grid library. Purchase a [commercial license](https://rv-grid.com/pro) for advanced features and support. ## MIT vs. Commercial licenses The Revolist team has been building MIT-licensed components and we’re committed to the continued advancement of our open-source libraries. Anything we release under an MIT license will remain MIT-licensed forever. We offer commercial licenses to developers who need the most advanced components and features that can’t reasonably be maintained by the open-source community alone. These licenses make it possible for us to support a full-time staff of engineers. Rest assured that when we release features commercially, it’s only because we believe you won’t find a better MIT-licensed alternative anywhere else. See the [Pricing page](https://rv-grid.com/pro) for a detailed feature comparison. ## Plans ### Community plan The free Community version of RevoGrid contains components and features that we believe are maintainable by contributions from the open-source community. It’s published under an MIT license and it’s free forever. ### Pro The Pro version is available under a commercial license and is distributed through an [advanced portal](https://pro.rv-grid.com/) aimed at providing comprehensive user support and extended documentation. [This portal](https://pro.rv-grid.com/) offers users exclusive access to detailed guides, use case examples, troubleshooting, and more to help streamline the development process. #### Light plan RevoGrid Pro expands on the Community version with more advanced features and functionality. The Pro version comes with cell merge, formula, charts, and excel export; you also gain access to the advanced column stretching, and expandable Tree View. The Pro version is available under a commercial license — visit the [Pricing page](https://rv-grid.com/pro) for details. #### Advanced plan Unlocks the most advanced features of RevoGrid, including the JavaScript Pivot Table component, Gantt Chart, AI, premium support, private GitHub repository access, totals, drill-down, field panels, custom aggregations, and server-side analytics contracts. It also includes everything offered in the Pro Lite plan. The Pro Advanced version is available under a commercial license—visit the [Licensing page](https://rv-grid.com/pro/policies/license) for details. ## Upgrading The npm packages of any given plan are an extension for the Community version. To upgrade, you must install the respective paid package and add all imports accordingly. Below are upgrading scenarios: ### From Community to Pro Install the Pro package, then update all imports accordingly: ```typescript import RevoGrid from '@revolist/vue3-datagrid'; +import { PivotPlugin } from '@revolist/revogrid-pro'; ``` ### From Pro to Pro Advanced Contact us to upgrade to Pro Advanced. ### Evaluation (trial) access Yes, you can evaluate RevoGrid Pro before purchasing. The public trial lasts 30 days and can be installed immediately by teams that need to validate Pro or Pro Advanced modules. Start with the [Get Pro Trial](https://rv-grid.com/trial) page for installation instructions, public demo links, trial limits, and the path from evaluation to production. For production license quantity details, see the relevant clause in the [EULA](https://rv-grid.com/pro/policies/license). --- # Evaluate RevoGrid Pro Source: https://rv-grid.com/trial Description: Start evaluating RevoGrid Pro immediately with public trial access, a no-login npm registry, and a ready-to-run public starter. This page is rendered from VitePress frontmatter and Vue components; no standalone Markdown body is available in the normalized export. --- # Considering Removing the Attribution? 🤔 Source: https://rv-grid.com/guide/attribution # Considering Removing the Attribution? 🤔 If you’re thinking about removing the attribution, we’d first like to mention: **If you’re using RevoGrid at your organization and making money from it, we rely on your support to keep RevoGrid developed and maintained under an MIT License.** Before you remove the attribution, see [the ways you can support RevoGrid](https://rv-grid.com/pro) to keep it running. Are you using RevoGrid for a **personal project**? Awesome! 🎉 Go ahead and remove the attribution. You can support us by: - Reporting any bugs 🐞 you find - Sending us screenshots 📸 of your projects - Starring us ⭐ on [GitHub](https://github.com/revolist/revogrid) If you start making money using RevoGrid or use it in an organization in the future, we would ask that you re-add the attribution or sign up for our [Pro membership](https://rv-grid.com/pro). **Thank you for supporting the RevoGrid team!** ✌🏻 --- # Contributing Source: https://rv-grid.com/guide/CONTRIBUTING # Contributing Thank you for your interest in contributing to RevoGrid! 🎉 ## Why Contribute? Contributing to RevoGrid not only offers developers the chance to enhance their skills and collaborate on cutting-edge data grid technology but also presents a unique opportunity for professional growth and financial gain. By participating in the development of RevoGrid, contributors can directly influence a tool used by companies worldwide, adding significant value to their professional portfolio. Moreover, standout contributors may have the opportunity to join our team full-time or benefit from paid project work, tapping into new career opportunities and monetary rewards. Contributing to RevoGrid is more than just coding—it's a chance to join a community that rewards your expertise and dedication with tangible benefits. ## Contributing Etiquette Please see our [Contributor Code of Conduct](https://rv-grid.com/guide/CODE_OF_CONDUCT) for information on our rules of conduct. ## Reporting a Bug * It is required that you clearly describe the steps necessary to reproduce the issue you are encountering. Diagnosing issues without clear reproduction steps is extremely time-consuming and not sustainable. * The issue list of this repository is exclusively for bug reports and feature requests. Non-conforming issues will be closed immediately. * Issues with no clear steps to reproduce will not be triaged. * If you think you have found a bug, please check if it has already been [reported](https://github.com/revolist/revogrid/issues). You can search through existing issues and include closed ones as it may have been resolved. * If a bug report already exists, please upvote it using the :+1: reaction on the GitHub Issue summary to avoid "+1" comments. * Next, [create a new issue](https://github.com/revolist/revogrid/issues/new) that thoroughly explains the problem. * Please fill out the issue form completely before submitting. * Please only include one bug per issue. ## Requesting a Feature * Before requesting a feature, check if it has already been [proposed](https://github.com/revolist/revogrid/issues). * If a feature request already exists, please support it using the :+1: reaction on the GitHub Issue summary. * Next, [create a new feature request](https://github.com/revolist/revogrid/issues/new?assignees=&labels=&projects=&template=feature_request.yml&title=feat%3A+) that thoroughly explains the desired feature. * Please fill out the feature request form completely before submitting. * Please only include one feature request per report. ## Creating a Pull Request * We appreciate your willingness to contribute! Before submitting a pull request, please [create an issue](#reporting-a-bug) discussing the bug or feature request and indicate that you plan to work on it. If an issue already exists, please comment on that issue stating your intention to submit a pull request. This helps us track pull requests and ensure there is no duplicated effort. ### Setup 1. Fork the repo. 2. Clone your fork. 3. Create a branch for your changes. 4. Run `npm install` to install dependencies. 5. Make your changes. ### Making Sure Your Changes Are Ready 1. Add unit tests for any new or changed functionality. Look at existing tests for guidance on how to write tests. 2. Run `npm run build` to ensure your code compiles correctly. 3. Run `npm test` to make sure all tests pass. ### Submitting Your Changes After you've made sure all tests pass: 1. Push your changes to your fork. 2. Submit a pull request to the RevoGrid repository. 3. Provide a detailed description of your changes and reference the issue number. ### Commit Message Format We follow the [Angular Commit Message Format](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#commits): * **Type**: feat, fix, docs, style, refactor, perf, test, chore, revert. * **Scope**: The scope could be anything specifying the place of the commit change. * **Subject**: Brief description of the change. ## License By contributing to RevoGrid, you agree that your contributions will be licensed under its MIT License. --- # RevoGrid Migration Guides Source: https://rv-grid.com/guide/migration Description: Review RevoGrid version changes and upgrade notes, including migration guidance for v2, v3, and v4 projects. ## Version 4.28.0 ### Breaking change: Default filter conditions are now visible Opening an empty column filter panel now displays one removable draft condition. String columns start with **Contains**, number columns start with **=**, and other filter families use their first available operator. The draft does not filter rows, emit filtering events, or mark the column as filtered until the user enters a value or explicitly selects an operator. To preserve the previous empty-panel behavior for the whole grid, disable default filter drafts in the filter configuration: ```ts grid.filter = { defaultFilter: false }; ``` To disable the draft for only one column, use the structured column filter configuration: ```ts grid.columns = [ { prop: 'name', filter: { type: 'string', default: false }, }, ]; ``` See [Filtering](https://rv-grid.com/guide/filters#default-filter-conditions) for column overrides and the complete draft lifecycle. ## Version 2.0+ - Introduced the plugin system, grouping, sorting, and filtering. ## Version 3.0+ - **Breaking Changes**: - Removed the redundant viewport component. - Renamed classes to support Bootstrap and other libraries: - `row` -> `rgRow` - `col` -> `rgCol` - `data-cell` -> `rgCell` - `data-header-cell` -> `rgHeaderCell` - Migrated all method names to lowercase to align with modern event naming conventions. For example, `afterEdit` is now `afteredit`. Check the API for details. - Added support for pure ESM modules to enable the use of the grid in all modern frontend tooling like Vite, Parcel, etc. You can now import custom elements without lazy loading. Note that you are responsible for polyfills. ## Version 4.0+ :::tip For a comprehensive migration guide check the [migration guide](https://rv-grid.com/guide/migrations/v4). ::: - **Summary on Breaking Changes**: - Redesigned type support: - Removed deprecated namespaces `RevoGrid`, `Selection` and others from type imports. Use direct import instead. For example: - **Before**: `RevoGrid.ColumnRegular` - **Now**: `ColumnRegular`; ... - Improved type imports. For example: - **Before**: `import { RevoGrid } from '@revolist/revogrid/dist/types/interfaces'` - **Now**: `import { ColumnRegular } from '@revolist/revogrid'`. - Changed viewport type names everywhere. For example, before: `rowDefinitions: [{ type: "row", index: 0, size: 145 }]`, after: `rowDefinitions: [{ type: "rgRow", index: 0, size: 145 }]`. - Updated [event](https://rv-grid.com/guide/api/events) naming convention. Review your [event](https://rv-grid.com/guide/api/events) usage. [Event names](https://rv-grid.com/guide/api/events) are all lowercase now and are aligned with modern event naming conventions. For example, `afterEdit` -> `afteredit`. Check migration guide for details. - **Major improvements**: - Rethought the entire framework approach. Introduced [Pro](https://rv-grid.com/pro/) version with advance support and pro features. - Updated scrolling system for better mobile support. - Advance template support. Introduced `additionalData` for templates and editors. `Prop` gives access to parent/root app context. - Redesigned the documentation. - Fixed major issues and significantly improved overall performance, making the grid multiple time faster. - Enhanced plugin support - now with full access to grid providers. - Provided full framework support and native render for [Angular](https://rv-grid.com/guide/angular/), [React](https://rv-grid.com/guide/react/), [Svelte](https://rv-grid.com/guide/svelte/), and [Vue](https://rv-grid.com/guide/vue3/), with partial support for Ember. --- # Demo React Data Grid and Table Source: https://rv-grid.com/guide/demos/react/react-datagrid Description: Try the RevoGrid React data grid demo with virtual rows and columns, editable cells, high-performance rendering, and React integration examples. # React Data Grid Demo Use this React demo to start a RevoGrid table with virtualized rows and columns, editable cells, and high-performance rendering for large datasets. [![Edit react-revogrid-start](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/react-revogrid-start-29fm5z) --- # React Native Cell component in Data Grid Source: https://rv-grid.com/guide/demos/react/react.cell Description: Native cell template rendering in RevoGrid for React Table, allowing the use of custom React components inside grid cells. # React Custom Cell Template Demo [![Edit react-revogrid-cell](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/react-revogrid-cell-jgt3mv) ### Key Considerations for Custom Cell Templates - **Data Access**: Each custom cell component will have access to the data for that row via its props. The primary prop that is passed to custom renderers is the value of the cell. - **Performance**: Custom renderers can impact grid performance, especially with large datasets. RevoGrid optimizes rendering by only updating cells that have changed, but it’s important to keep performance in mind when creating complex cell templates. - **Conditional Rendering**: You can use conditional logic inside your custom cell component to change its appearance based on the data. For example, you can display different colors or icons based on numeric values or boolean flags. - **Event Handling**: Custom cells can include event handlers, such as onClick, onChange, etc., to make the grid interactive. This is ideal for rendering editable fields, buttons, or custom controls. ### Advanced Use Cases RevoGrid’s native rendering support opens up even more complex scenarios where you can render interactive components, such as: - **Dynamic Dropdowns**: Populate a dropdown inside a cell based on the data in the grid or external sources. - **Custom Formatting**: Display values with custom formatting, such as currency symbols, percentages, or styled numbers. - **Inline Editing**: Build advanced inline editing components, such as date pickers, checkboxes, or toggles, inside grid cells. --- # React Native Editor Data Grid component Source: https://rv-grid.com/guide/demos/react/react.editor Description: Learn how to use React for native editor rendering in RevoGrid, allowing custom in-cell editing with React components. # React Data Grid Cell Editor Demo RevoGrid allows for even more complex custom editors by passing data and handling events like onChange or onBlur. You can create more interactive editors such as input fields, checkboxes, or dropdowns that allow users to update cell values directly. [![Edit react-revogrid-editor](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/react-revogrid-cell-vdjyp2) ### Advanced Use Cases You can extend RevoGrid’s native editor rendering by implementing more sophisticated editors, such as: - **Date Pickers**: Use a date picker React component to edit date values in a column. - **Select Menus**: Render a dropdown menu with dynamic options based on other grid data or external sources. - **Multistep Editors**: Create complex multi-field editors for advanced data entry. --- # React Grouping View Data Grid Table Source: https://rv-grid.com/guide/demos/react/react-grouping Description: Group rows in a React RevoGrid data grid with an interactive grouping demo and standalone source example. # React Row Grouping Data Grid Demo Group rows in a React data grid with RevoGrid and an interactive row grouping example. [![Edit react-revogrid-grouping](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/react-revogrid-grouping-h5f9sh?from-embed=) --- # React Multi Select Data Grid Table Source: https://rv-grid.com/guide/demos/react/react-multiselect Description: Build a React multiselect data grid with RevoGrid, virtual rendering, and an interactive selection demo. # React Multi Select Data Grid Demo Use this React demo to render a multiselect data grid with RevoGrid and virtualized selection behavior. [![Edit react-revogrid-multiselect](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/react-revogrid-multiselect-mgy263) --- # React Tree Data Grid Source: https://rv-grid.com/guide/demos/react/react-tree Description: Explore the free RevoGrid React core tree pattern first, then see how RevoGrid Pro TreeDataPlugin adds expand and collapse controls, sticky parents, and hierarchy-aware behavior. Start with the free/core tree pattern: flatten parent-child rows into display order, add a `level` field, and render indentation in a React cell template. [![Edit react-revogrid-tree](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/react-revogrid-tree-7mq6cm?from-embed=) ## Pro Tree Data RevoGrid Pro adds `TreeDataPlugin` when you need built-in expand and collapse controls, hierarchy-aware row visibility, sticky parent rows, row selection integration, row drag integration, filtering, sorting, and virtualization over advanced tree structures. Use the full [React Tree Data guide](https://rv-grid.com/guide/react/tree) for both approaches and the [Advanced Tree Data guide](https://rv-grid.com/guide/tree-data) for the complete Pro tree model. --- # Demo Angular Data Grid Standalone Source: https://rv-grid.com/guide/demos/angular/angular-datagrid Description: Start a standalone Angular data grid with RevoGrid, virtual scrolling, editable cells, and framework-native integration examples. # Angular Data Grid Demo Use this Angular standalone demo to render RevoGrid with virtual scrolling, editable cells, and framework-native setup. [![Edit RG Cell (Angular Standalone)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-cell-angular-standalone-t4lrz2) --- # Native Cell component - Angular Data Grid Source: https://rv-grid.com/guide/demos/angular/angular.cell Description: Render native Angular components inside RevoGrid cells with this Angular data grid cell template demo. [![Edit RG Cell (Angular Standalone)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-cell-angular-standalone-t4lrz2) --- # Column resize - Angular Data Grid Source: https://rv-grid.com/guide/demos/angular/angular.column-resize Description: Resize Angular data grid columns with RevoGrid and combine column sizing with custom cell templates. [![Edit RG Table column resize & Cell Template [Angular]](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/table-column-resize-and-cell-template) --- # Header component & Tooltip - Angular Data Grid Source: https://rv-grid.com/guide/demos/angular/angular.header Description: Customize Angular data grid headers and tooltips with RevoGrid header component rendering. # Header Component and Tooltip Demo [![Edit RG - Header Tooltip (Angular standalone)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-header-tooltip-angular-standalone-yz77gy) --- # Native Editor component - Angular Data Grid Source: https://rv-grid.com/guide/demos/angular/angular.editor Description: Build a native Angular cell editor for RevoGrid with this editable data grid demo. # Native Editor Component Demo [![Edit RG Editor (Angular Standalone)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-editor-angular-standalone-lgc3pr) --- # Native Date Editor - Angular Data Grid Source: https://rv-grid.com/guide/demos/angular/angular.editor-custom Description: Use a custom native Angular date editor inside RevoGrid cells with this standalone Angular demo. [![Edit RG - Custom date editor (Angular standalone)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-custom-date-editor-angular-standalone-548j6x) --- # Focus Catch - Angular Data Grid Source: https://rv-grid.com/guide/demos/angular/angular.focus Description: Capture and handle RevoGrid focus events in an Angular standalone data grid demo. # Focus Catch Demo [![Edit RG Focus Catch (Angular Standalone) ](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-focus-catch-angular-standalone-3rmdt3) --- # Inventory Spreadsheet Demo - Angular Data Grid Source: https://rv-grid.com/guide/demos/angular/angular.full-demo Description: Open an Angular inventory spreadsheet demo built with RevoGrid for editable rows, tabular business data, and standalone Angular setup. # Inventory Spreadsheet Demo Use this Angular inventory spreadsheet demo to explore editable business data workflows with RevoGrid. [![Edit RG Inventory List Demo (Angular)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-inventory-list-demo-angular-forked-rzq2jj) --- # Getting Started Module - Angular Data Grid Source: https://rv-grid.com/guide/demos/angular/angular.sample.module Description: Start RevoGrid in an Angular module-based application with this Angular data grid demo. ## Getting Started Module [![Edit RG Start (Angular Module)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-start-angular-module-3ls7pr) --- # Angular Tree Data Grid Source: https://rv-grid.com/guide/demos/angular/angular-tree Description: Explore an Angular tree data grid with RevoGrid Pro TreeDataPlugin, flat parent-child rows, expandable hierarchy controls, sticky parents, drag-and-drop, filtering, and virtualized rendering. Angular can use the free/core tree pattern with a flattened `source` and an indented cell template. The live Angular widget below shows the Pro upgrade path, where the plugin manages tree state and interactions for you. ## Pro Tree Data Use the full [Angular Tree Data guide](https://rv-grid.com/guide/angular/tree) for both approaches and the [Advanced Tree Data guide](https://rv-grid.com/guide/tree-data) for the complete Pro tree model. --- # Get Started with Vue 3 Data Grid Demo - Composition API Source: https://rv-grid.com/guide/demos/vue/vue3-datagrid Description: Start a Vue 3 Composition API data grid with RevoGrid, virtual scrolling, editable cells, and source code examples.
::: details Source code [Git](https://github.com/revolist/revogrid-docs/tree/main/demo/vue/vue3-datagrid.vue) [Codesandbox](https://codesandbox.io/p/sandbox/rg-start-vue-3-composition-api-3775m4) ::: code-group <<< @/demo/vue/vue3-datagrid.vue ::: --- # Get Started with Vue 3 Data Grid Demo - Options API Source: https://rv-grid.com/guide/demos/vue/vue.sample.options Description: Start a Vue 3 Options API data grid with RevoGrid, virtual scrolling, editable cells, and source code examples.
::: details Source code [Git](https://github.com/revolist/revogrid-docs/tree/main/demo/vue/vue.sample.options.example.vue) [Codesandbox](https://codesandbox.io/p/sandbox/rg-start-vue-3-options-ap-8mlqjx) ::: code-group <<< @/demo/vue/vue.sample.options.example.vue ::: --- # Native Cell component (Composition API) - Vue 3 Data Grid Source: https://rv-grid.com/guide/demos/vue/vue.cell.composition Description: Render native Vue 3 Composition API components inside RevoGrid cells with a custom cell template demo. ## Vue 3 - Native Cell Component (Composition API)
::: details Source code [Git](https://github.com/revolist/revogrid-docs/tree/main/demo/vue/vue.cell.composition.example.vue) [Codesandbox](https://codesandbox.io/p/sandbox/rg-cell-vue-3-composition-api-cvv97n) ::: code-group <<< @/demo/vue/vue.cell.composition.example.vue <<< @/demo/vue/vue.cell.composition.example-cell.vue ::: --- # Vue 3 Data Grid Cell Editor component (Composition API) Source: https://rv-grid.com/guide/demos/vue/vue.editor.composition Description: Build a Vue 3 Composition API cell editor for RevoGrid with custom editor components and source code.
::: details Source code [Git](https://github.com/revolist/revogrid-docs/tree/main/demo/vue/vue.editor.composition.example.vue) [Codesandbox](https://codesandbox.io/p/sandbox/rg-editor-vue-3-composition-api-sl8vvw) ::: code-group <<< @/demo/vue/vue.editor.composition.example.vue <<< @/demo/vue/vue.editor.composition.example-editor.vue ::: --- # Multi Select Virtual List - Vue 3 Data Grid Source: https://rv-grid.com/guide/demos/vue/vue.select Description: Build a Vue 3 multiselect virtual list with RevoGrid and Composition API source examples. # Vue 3 - Multi Select (Composition API) :::tabs == Preview == Source code <<< @/demo/vue/vue.select.vue == Codesandbox [![Edit RG Select All (Vue 3 Composition api)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-select-all-vue-3-composition-api-4myr3l) ::: --- # Row Grouping - Vue 3 Data Grid Source: https://rv-grid.com/guide/demos/vue/vue.grouping Description: Group rows in a Vue 3 RevoGrid data grid with a Composition API demo and interactive grouping example. # Vue 3 - Row Grouping Demo [![Edit RG Grouping (Vue 3 Composition api)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-start-vue-3-composition-api-forked-ffwdrt?file=%2Fsrc%2FApp.vue%3A19%2C41) --- # Vue 3 Tree Data Grid Source: https://rv-grid.com/guide/demos/vue/vue-tree Description: Explore the free RevoGrid Vue 3 core tree pattern first, then see how RevoGrid Pro TreeDataPlugin adds expand and collapse controls, sticky parents, and hierarchy-aware behavior. # Vue 3 - Tree Data Grid Start with the free/core tree pattern: flatten parent-child rows into display order, add a `level` field, and render indentation in a Vue cell template. ## Pro Tree Data RevoGrid Pro adds `TreeDataPlugin` when you need built-in expand and collapse controls, hierarchy-aware row visibility, sticky parent rows, row selection integration, row drag integration, filtering, sorting, and virtualization over advanced tree structures. Use the full [Vue 3 Tree Data guide](https://rv-grid.com/guide/vue3/tree) for both approaches and the [Advanced Tree Data guide](https://rv-grid.com/guide/tree-data) for the complete Pro tree model. --- # Getting Started - Vue 2 Data Grid Source: https://rv-grid.com/guide/demos/vue/vue2-datagrid Description: Start a Vue 2 data grid with RevoGrid using a basic editable grid setup and CodeSandbox example. [![Edit RG Start (Vue 2)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-start-vue-2-3zl8hd) --- # Native Cell component - Vue 2 Data Grid Source: https://rv-grid.com/guide/demos/vue/vue2.cell Description: Render native Vue 2 components inside RevoGrid cells with this cell template demo. # Native Cell Component - Vue 2 Data Grid [![Edit RG Cell (Vue 2)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-cell-vue-2-78q5fl) --- # Native Editor component - Vue 2 Data Grid Source: https://rv-grid.com/guide/demos/vue/vue2.editor Description: Build a native Vue 2 editor component for editable RevoGrid cells. # Native Editor Component - Vue 2 Data Grid [![Edit RG Editor (Vue 2)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-editor-vue-2-9zr8ng) --- # Native Date Editor component - Vue 2 Data Grid Source: https://rv-grid.com/guide/demos/vue/vue2.date Description: Use a native Vue 2 date editor with RevoGrid column types and editable grid cells. # Native Date Editor Component - Vue 2 Data Grid [![Edit RG Date Column Localization (Vue 2)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-date-column-localization-vue-2-nnd8w3) --- # Grouping - Vue 2 Data Grid Source: https://rv-grid.com/guide/demos/vue/vue2.grouping Description: Group rows in a Vue 2 data grid with RevoGrid and a focused row grouping demo. [![Edit RG Grouping (Vue 2)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-grouping-vue-2-2m3lzc) --- # Multiselect Virtual list - Vue 2 Data Grid Source: https://rv-grid.com/guide/demos/vue/vue2.list Description: Render a virtual multiselect list in Vue 2 with RevoGrid for large selectable datasets. # Multiselect Virtual List - Vue 2 Data Grid [![Edit RG Infinity List (Vue 2 Options Api)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-infinity-list-vue-2-options-api-wgd96l) --- # Multi Select Data Grid Virtual list - Vue 2 Data Grid Source: https://rv-grid.com/guide/demos/vue/vue2.select Description: Build a Vue 2 RevoGrid select-all list with virtual rendering and multiselect behavior. # Multi Select Data Grid Virtual List - Vue 2 Data Grid [![Edit RG Select All List (Vue 2 Options Api)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-select-all-list-vue-2-options-api-rr25l9) --- # Demo JavaScript Data Grid Source: https://rv-grid.com/guide/demos/js/js.overview Description: Try a standalone JavaScript data grid demo with RevoGrid, virtual scrolling, editable data, and source code for browser-based setup. # JavaScript Data Grid Demo Use this standalone JavaScript demo to see RevoGrid render editable tabular data with virtual scrolling and fast browser performance. :::preview #demo-overview .rv-overview :path /demo/js/js.overview.example ::: ::: details Source code [Git](https://github.com/revolist/revogrid-docs/tree/main/demo/js/js.overview.example.ts) [Codesandbox](https://codesandbox.io/p/sandbox/rg-quick-overview-88rf36?from-embed=) ::: code-group <<< @/demo/js/js.overview.example.ts#snippet <<< @/json/stock.json ::: --- # Row Grouping in Data Grid Source: https://rv-grid.com/guide/demos/js/js.grouping Description: Learn how to configure row grouping in RevoGrid using TypeScript. Easily group rows based on specific properties for better data organization and visualization. [Interface: GroupingOptions](https://rv-grid.com/guide/types/TypeAlias.GroupingOptions) Row grouping in RevoGrid allows you to organize rows based on a specific property, making it easy to categorize and visualize hierarchical data. With RevoGrid’s powerful features, you can set up grouping with minimal configuration. [![Edit RG - Grouping (Standalone)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-start-standalone-forked-xkr9wq) --- # Individual row sizes Source: https://rv-grid.com/guide/demos/js/js.custom.rows Description: Configure individual RevoGrid row sizes in a standalone JavaScript data grid demo. # Individual Row Sizes Demo [![Edit RG -Custom sizes per row](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-quick-overview-forked-yc77yn?file=%2Fsrc%2Findex.ts%3A22%2C13) --- # Date column Source: https://rv-grid.com/guide/demos/js/js.date Description: Add a date column to a standalone RevoGrid JavaScript data grid with date editor behavior. # Date Column Demo
[![Edit RG - Date (Standalone)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-date-standalone-jwwwd8?file=%2Fsrc%2Findex.ts%3A27%2C62) --- # Filter Plugin Source: https://rv-grid.com/guide/demos/js/js.filtering Description: Configure RevoGrid filtering in a standalone JavaScript data grid demo with clear filter behavior. # Filter Plugin Demo
[![Edit RG - Filtering defined](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rg-filtering-defined-z9mzgr) --- # JSX and TSX Data Grid Template Demo Source: https://rv-grid.com/guide/demos/jsx/jsx.template Description: Render custom RevoGrid cell content with JSX and TSX templates in a TypeScript data grid demo. # JSX/TSX - DataGrid Template Demo ## TypeScript JSX Cell Template Demo [Check out this sample.](https://codesandbox.io/s/revo-grid-vanilla-jsx-zj0q6?file=/src/index.js) We use babel-jsx with minimal configuration settings. --- # TypeScript Tree Data Grid Source: https://rv-grid.com/guide/demos/jsx/jsx-tree Description: Explore the free RevoGrid TypeScript core tree pattern first, then see how RevoGrid Pro TreeDataPlugin adds expand and collapse controls, sticky parents, and hierarchy-aware behavior. Start with the free/core tree pattern: flatten parent-child rows into display order, add a `level` field, and render indentation in a cell template. ## Pro Tree Data RevoGrid Pro adds `TreeDataPlugin` when you need built-in expand and collapse controls, hierarchy-aware row visibility, sticky parent rows, row selection integration, row drag integration, filtering, sorting, and virtualization over advanced tree structures. Use the full [TypeScript Tree Data guide](https://rv-grid.com/guide/ts/tree) for both approaches and the [Advanced Tree Data guide](https://rv-grid.com/guide/tree-data) for the complete Pro tree model. --- # JavaScript Data Grid Demo for Large Datasets Source: https://rv-grid.com/demo Description: Test RevoGrid with a large editable dataset, virtual scrolling, filtering, sorting, and framework-ready JavaScript data grid interactions.
--- # AI Prompt Library Data Grid Demo Source: https://rv-grid.com/demo/ai-prompts Description: Explore a searchable, filterable, and editable AI prompt catalog with multiline content and instant local data loading in the open-source Core grid.
--- # Project Portfolio Row Grouping Demo Source: https://rv-grid.com/demo/project-portfolio Description: Explore a realistic project portfolio with two-level row grouping, custom progress cells, sorting, and filtering in the open-source Core grid.
--- # Tree Data Grid Hierarchy Demo Source: https://rv-grid.com/demo/tree-data Description: Explore expandable hierarchical data grid rows with sticky parents, animated transitions, drag ordering, filters, selection, and export.
--- # Advanced Data Grid Filtering Demo Source: https://rv-grid.com/demo/filtering Description: Combine filter presets, global search, expressions, selection cascades, date rules, and numeric sliders in the RevoGrid Pro filtering demo.
--- # Infinity Scroll Data Grid Demo Source: https://rv-grid.com/demo/infinity-scroll Description: Load remote data grid rows in buffered chunks with server-side sorting, filtering, pinned summaries, and Excel export in RevoGrid Pro.
--- # Column Collapse Data Grid Demo Source: https://rv-grid.com/demo/column-collapse Description: Collapse grouped data grid columns into sealed summary fields, then expand, filter, resize, and select rows in this RevoGrid Pro demo.
--- # Context Menu & Cell Formatting Demo Source: https://rv-grid.com/demo/context-menu Description: Open selection-aware menus for cells, rows, columns, and grouped headers, then apply rich cell formatting in this RevoGrid Pro data grid demo.
--- # Row Master Detail Data Grid Demo Source: https://rv-grid.com/demo/row-master Description: Expand hierarchical project rows into rich master-detail panels with asynchronous content and virtualized grid navigation in RevoGrid Pro.
--- # Audit History Data Grid Demo Source: https://rv-grid.com/demo/audit-history Description: Track attributed data grid edits, compare revisions, export audit records, and restore earlier cell values in the RevoGrid Pro audit history demo.
--- # Project Tracker Data Grid Demo Source: https://rv-grid.com/demo/color Description: Edit projects, owners, priorities, statuses, and deadlines in a color-coded RevoGrid Pro project tracker with filtering and drag ordering.
--- # Grid, Kanban, Gantt Charts & Event Scheduler Demo Source: https://rv-grid.com/demo/planning Description: Edit one shared task model across synchronized Data Grid, Kanban, Gantt, Scheduler, and Calendar views in RevoGrid Pro Advanced.
--- # JavaScript Gantt Chart Demo – RevoGrid Gantt Source: https://rv-grid.com/demo/gantt Description: Try RevoGrid Gantt with editable tasks, dependencies, milestones, drag-and-resize scheduling, resources, calendars, and critical path.
--- # Large Dataset Gantt Demo Source: https://rv-grid.com/demo/gantt-big-data Description: Explore 10,000 virtualized Gantt tasks and 19,796 dependencies across a three-month project while keeping timeline rendering responsive.
--- # 20Y-Timeline Gantt Demo Source: https://rv-grid.com/demo/gantt-horizontal-big-data Description: Explore 100 linked tasks across a twenty-year Gantt timeline with month-and-quarter scaling and responsive horizontal rendering.
--- # JavaScript Scheduler and Shift Planning Demo Source: https://rv-grid.com/demo/event-scheduler Description: Schedule employee shifts and resources with RevoGrid Pro Advanced using calendar views, conflict detection, and drag-to-create, move, or resize.
--- # JavaScript Kanban Board Demo | RevoGrid Kanban Source: https://rv-grid.com/demo/kanban Description: Try RevoGrid Kanban with configurable workflow columns, swimlanes, drag-and-drop ordering, WIP limits, rules, and inline editing.
--- # 50K-Task JavaScript Kanban Demo | RevoGrid Kanban Source: https://rv-grid.com/demo/kanban-performance Description: Explore 50,000 virtualized tasks in RevoGrid Kanban across ten workflow columns and two team swimlanes.
--- # 100K JavaScript Kanban Demo | RevoGrid Kanban Source: https://rv-grid.com/demo/kanban-server-loading Description: Page through 100,000 remote cards in RevoGrid Kanban with virtualized loading, accurate totals, and request status.
--- # JavaScript Pivot Table Component Demo Source: https://rv-grid.com/demo/pivot Description: Try the RevoGrid JavaScript pivot table component with drag-and-drop fields, aggregation, filtering, drill-down, grouped axes, totals, and export.