SVAR Svelte DataGrid

repository·main·Indexed 42 days ago

https://github.com/svar-widgets/grid

A high-performance data table component for Svelte applications featuring virtual scrolling, in-cell editing, and advanced filtering. Supports Svelte 5 via @svar-ui/svelte-grid and Svelte 4 via wx-svelte-grid@1.3.3. Includes built-in support for frozen columns, row reordering, CSV export, and WAI-ARIA accessibility compliance.

Tokens
14.5K
Snippets
52
Records
54
Agent score
53%

What's inside SVAR Svelte DataGrid

  1. Overview of SVAR Svelte DataGrid features

    main

    SVAR Svelte DataGrid is a high-performance component designed for complex, interactive tables with large datasets. Key capabilities include:

    • Performance: Virtual scrolling and dynamic loading.
    • Editing: In-cell editing with various editors (datepicker, combo, select, rich select, etc.) or an external editor.
    • Data Manipulation: Sorting (multiple columns), advanced filtering (including natural language), paging, and row reordering via drag-and-drop.
    • Layout: Frozen columns, expandable/collapsible columns, and tree-like structures.
    • UI/UX: Customizable toolbars, context menus, tooltips, and built-in dark/light skins (CSS-based, no Tailwind dependency).
    • Data Integration: RestDataProvider for backend binding and CSV export.
    • Advanced Features: Undo/redo, keyboard navigation, print support, and WAI-ARIA accessibility compliance.
  2. Use the Grid component in Svelte

    main

    To implement the data grid, import the Grid component from @svar-ui/svelte-grid. You must provide a data array containing your records and a columns array defining the grid structure. Each column object can specify properties like id, header, width, flexgrow, sort, and editor types.

    <script>
    	import { Grid } from "@svar-ui/svelte-grid";
    
    	const data = [
    		{
    			id: 12,
    			name: "Alex Brown",
    			year: 1974,
    		},
    	];
    	const columns = [
    		{
    			id: "name",
    			header: "Title",
    			flexgrow: 1,
    			sort: true,
    			editor: "text",
    		},
    		{
    			id: "year",
    			header: "Year",
    			width: 100,
    			sort: true,
    			editor: "text",
    		},
    	];
    </script>
    
    <Grid {data} {columns} />
  3. Install SVAR Svelte DataGrid

    main

    The installation command depends on the version of Svelte you are using. Use the @svar-ui/svelte-grid package for Svelte 5, or the wx-svelte-grid@1.3.3 package for Svelte 4.

    # For Svelte 5
    npm install @svar-ui/svelte-grid
    
    # For Svelte 4
    npm install wx-svelte-grid@1.3.3
  4. Customizing filter logic with custom handlers

    main

    The grid supports custom filtering logic by allowing you to override the default handlers. When creating a column, you can provide a custom handler within the filter.config object. If a custom handler is present, the grid will use it instead of the built-in handlers for the specified TFilterType.

    Built-in handlers include:

    • text: Case-insensitive substring match.
    • richselect: Strict equality match.
    • datepicker: Date equality match (ignoring time).
    • multiselect: Checks if any value in the column's array exists within the filter's array.
  5. Access the Grid store from child components

    main

    The Grid component provides a way for child components to access the grid's internal state and methods using Svelte's getContext API.

    Any component rendered within the Grid component's subtree can call getContext('grid-store') to retrieve the following methods:

    • getState(): Get the current state.
    • getReactiveState(): Get the reactive state.
    • exec(event): Execute an event on the grid's event bus.
    • getRow(id): Retrieve a row by ID.
    <script>
      import { getContext } from 'svelte';
      const grid = getContext('grid-store');
      
      function handleAction() {
        const row = grid.getRow('some-id');
        grid.exec('some-event');
      }
    </script>
  6. Configure the Grid component

    main

    The Grid component is the primary entrypoint for rendering the data table. It accepts a columns array of IColumnConfig and various props to control styling, selection, and responsiveness.

    Key props include:

    • columns: An array of IColumnConfig defining the table structure.
    • rowStyle, columnStyle, cellStyle: Functions for dynamic styling of rows, columns, and cells.
    • multiselect: Boolean to enable multiple row selection.
    • reorder: Boolean to enable column reordering.
    • draggableRows: Boolean or a function (row: IRow) => boolean to enable row dragging.
    • responsive: An object mapping breakpoints to ISizeConfig and IColumnConfig[] for responsive layouts.
    • init: A callback (api: IApi) => void to access the grid API immediately after initialization.
    • hotkeys: Configuration for keyboard shortcuts.
    • autoConfig: Boolean or IColumnConfig for automatic configuration.
    • overlay: A string or Svelte Component to display as an overlay.

    Grid events are automatically generated from TMethodsConfig using a hyphen-to-camelCase conversion (e.g., a method row-select becomes the prop onRowSelect).

    <Grid
      columns={[
        { field: 'id', header: 'ID' },
        { field: 'name', header: 'Name', cell: MyCustomCell }
      ]}
      multiselect={true}
      reorder={true}
      rowStyle={(row) => row.active ? 'bg-blue-100' : ''}
    />
  7. Generate column CSS styles with getStyle()

    main

    The getStyle function generates a CSS string used to apply dimensions and positioning to grid columns. It supports fixed widths, flex growth, height, and sticky positioning for fixed columns.

    Parameters:

    • width: Number. Sets both width and min-width in pixels.
    • flexgrow: Number. Sets the flex-grow CSS property.
    • fixed: Object. If provided, enables position:sticky. Supports left and right properties.
    • left: Number. The offset for left sticky positioning.
    • right: Number. The offset for right sticky positioning.
    • height: Number. Sets the height in pixels.
    import { getStyle } from './columnWidth.js';
    
    // Example: A fixed-width, sticky-left column with 100px width
    const style = getStyle(100, 0, { left: 0 }, 0, null, null);
    // Returns: "min-width:100px;width:100px;position:sticky;left:0px;"
  8. Use createFilter to generate a predicate function

    main

    The createFilter function generates a single predicate function (obj: any) => boolean that evaluates whether a data object matches all active filter values. This is useful for manual filtering of data arrays.

    To use it, provide:

    1. filterValues: An object where keys correspond to column IDs and values are the filter criteria.
    2. columns: An array of IFilterColumn objects defining the grid structure and filter types.

    The resulting function performs an AND operation across all active filters; if any filter fails, the object is excluded.

    // Example usage of createFilter
    const activeFilters = { categoryId: 'electronics', status: 'active' };
    const columns = [
      {
        id: 'categoryId',
        header: [{ filter: { type: 'richselect' } }]
      },
      {
        id: 'status',
        header: [{ filter: { type: 'text' } }]
      }
    ];
    
    const isMatch = createFilter(activeFilters, columns);
    const filteredData = data.filter(isMatch);
  9. Apply theme wrappers: Material and Willow

    main

    The grid supports theme wrappers to apply specific visual styles and fonts.

    • Material: Applies Material design styling. Use the fonts prop (boolean) to control font loading.
    • Willow: Applies Willow styling. Use the fonts prop (boolean).
    • WillowDark: A dark mode variant of the Willow theme.

    Wrap your Grid or application content with these components to apply the theme.

    <Material fonts={true}>
      <Grid ... />
    </Material>
  10. Calculate pointer position with getPos

    main

    The getPos function calculates the pointer's position relative to a specific DOM node's offset. This is typically used to determine where inside an element a user has clicked or touched.

    Parameters:

    • ev: The event object (e.g., MouseEvent or TouchEvent).
    • node: The DOM node to calculate the offset against.

    Returns: An object { x, y } representing the pointer position relative to the node's top-left corner.

    import { getPos } from './path/to/reorder.js';
    
    // Inside an event handler
    const relativePos = getPos(event, targetNode);
    console.log(`Pointer is at ${relativePos.x}, ${relativePos.y} within the node`);
  11. Use the IApi interface to interact with the grid

    main

    The IApi interface provides the primary programmatic interface for controlling the grid and reacting to its state changes.

    Methods:

    • exec<A>(action: A, params?: ...): Executes an asynchronous action defined in TMethodsConfig. Returns a Promise<any>.
    • on<A>(action: A, callback: ...): Registers a listener for a specific action. The callback receives the action's configuration.
    • intercept<A>(action: A, callback: ...): Intercepts an action before it is processed.
    • detach(tag: IEventConfig['tag']): Removes listeners associated with a specific tag.
    • getState(): Returns the current IData state.
    • getReactiveState(): Returns an object where every key in IData is mapped to an IPublicWritable (allowing reactive updates in Svelte).
    export interface IApi {
    	exec: <A extends keyof TMethodsConfig | (string & {})>(
    		action: A,
    		params?: A extends keyof TMethodsConfig ? TMethodsConfig[A] : any
    	) => Promise<any>;
    	on: <A extends keyof TMethodsConfig | (string & {})>(
    		action: A,
    		callback: (
    			config: A extends keyof TMethodsConfig ? TMethodsConfig[A] : any
    		) => any,
    		config?: IEventConfig
    	) => void;
    	intercept: <A extends keyof TMethodsConfig | (string & {})>(
    		action: A,
    		callback: (
    			config: A extends keyof TMethodsConfig ? TMethodsConfig[A] : any
    		) => any,
    		config?: IEventConfig
    	) => void;
    	detach: (tag: IEventConfig["tag"]) => void;
    
    getState: () => IData;
    	getReactiveState: () => {
    		[Key in keyof IData]: IPublicWritable<IData[Key]>;
    	};
    	setNext: (ev: IEventBus<TMethodsConfig>) => void;
    	getStores: () => { data: DataStore };
    	getRow: (row: TID) => IRow;
    	getColumn: (column: TID) => IColumn;
    }
  12. Generate cell CSS classes with getCssName()

    main

    The getCssName function computes the CSS class string for a grid cell based on column properties, cell spanning, and vertical alignment. It handles special classes for sticky/fixed columns, including shadow effects for boundary cells.

    Parameters:

    • column: Object. Contains column configuration, including fixed (positioning object), _colindex, and fixed.leftSize.
    • cell: Object. Contains cell properties like colspan, rowspan, and vertical (boolean).
    • columnStyle: Function (optional). A callback that accepts a column and returns a string of additional CSS classes.

    Generated Classes:

    • wx-fixed: Applied to fixed/sticky columns.
    • wx-shadow: Applied to the boundary cell of a fixed column group to indicate a shadow effect.
    • wx-rowspan: Applied if cell.rowspan > 1.
    • wx-colspan: Applied if cell.colspan > 1.
    • wx-vertical: Applied if cell.vertical is true.
    import { getCssName } from './columnWidth.js';
    
    const column = { _colindex: 0, fixed: { left: 100, leftSize: 1 } };
    const cell = { colspan: 1, rowspan: 1, vertical: true };
    
    const classes = getCssName(column, cell);
    // Returns: "wx-fixed wx-vertical "