gridstack.js

repository·master·Indexed 27 days ago

https://github.com/gridstack/gridstack.js

A modern, mobile-friendly TypeScript/JS library for creating responsive, drag-and-drop dashboard layouts. It features no external dependencies and provides official wrappers for frameworks including Angular (v14+), React, Vue, Ember, and Knockout.

Tokens
50.5K
Snippets
158
Records
385
Agent score
92%

What's inside gridstack.js

  1. GridStackEngine Overview

    master

    The GridStackEngine is the core component that handles all grid layout calculations and node positioning without performing DOM operations. It manages collision detection, layout algorithms (compact, float, etc.), resizing, and movement logic.

    Note: Do not modify engine values directly; always use the main GridStack API to ensure DOM updates and events are triggered correctly.

  2. Widget reparenting (cross-grid DnD)

    master
    The Vue wrapper supports seamless widget reparenting during cross-grid drag-and-drop operations. Widget components are mounted only once and survive being moved between different grids. This is achieved using Vue's <Teleport> mechanism, which moves the slot content into the .grid-stack-item-content element of the target grid without destroying or remounting the component.
  3. Implement recommended layout patterns in React

    master

    To avoid conflicts with GridStack's DOM manipulation (such as dragging and reparenting), do not attempt to drive the grid exclusively by mapping over a React state array to render <GridStackItem> components.

    Recommended Approach: Define your layout as a JSON object passed to options.children. Use a components map where keys correspond to the component field on each widget. This allows React content to be rendered via createPortal into the .grid-stack-item-content element, ensuring the React tree remains mounted even when the DOM node moves during grid operations.

  4. Implement custom drag handles in React components

    master

    If you want to use a specific element inside your React component as the drag handle, you must:

    1. Configure the draggable.handle option in your GridStackOptions with the appropriate CSS selector.
    2. Call grid.refreshDragHandles(el) after your component renders so GridStack can attach listeners to the new element.

    If you are managing the item element yourself via useGridStack().grid, you must manually trigger this refresh using a useEffect hook.

    import { useEffect, useRef } from "react";
    import { useGridStack } from "gridstack/dist/react";
    
    function MyWidget() {
      const { grid } = useGridStack();
      const handleRef = useRef<HTMLDivElement>(null);
    
      useEffect(() => {
        if (!handleRef.current) return;
        const itemEl = handleRef.current.closest(".grid-stack-item") as HTMLElement | null;
        if (itemEl) grid?.refreshDragHandles(itemEl);
      }, [grid]);
    
      return (
        <div
          >
          <div ref={handleRef} className="my-drag-handle" style={{ cursor: "grab", padding: 8 }}>
            ☰ drag here
          </div>
          <p>content</p>
        </div>
      );
    }
    
    // Grid must be initialised with draggable.handle pointing at the same selector:
    const options: GridStackOptions = {
      draggable: { handle: ".my-drag-handle" },
      children: [{ id: "a", x: 0, y: 0, w: 3, h: 2, component: "MyWidget" }],
    };
    
    export function Board() {
      return <GridStack options={options} components={{ MyWidget }} />;
    }
  5. Legacy jQuery Application Setup (v5.1.1 and below)

    master

    Warning: This configuration is for versions prior to v6 and is no longer applicable to current versions.

    To use GridStack with jQuery and jQuery UI, you must use version 5.1.1 or earlier. This setup requires importing jquery and jquery-ui by name, which may require Webpack aliases to point to the specific files provided in the gridstack/dist/jq/ directory.

    HTML Include Options:

    • gridstack-h5.js: Native HTML5 drag&drop.
    • gridstack-jq.js: jQuery UI drag&drop (includes jQuery 3.5.1, jQuery UI 1.13.1, and jQuery UI Touch Punch 1.0.8).
    • gridstack-static.js: Static grid mode.
  6. Install and use the GridStack React wrapper

    master

    The React wrapper is included in the main gridstack package and is located at gridstack/dist/react.

    To use it, import the GridStack component and provide a GridStackOptions object. You must also import the GridStack CSS.

    CSS Requirements:

    @import "gridstack/dist/gridstack.css";
    
    .grid-stack {
      background: #fafad2;
    }
    .grid-stack-item-content {
      text-align: center;
      background-color: #18bc9c;
    }
    import { GridStackOptions } from "gridstack";
    import { GridStack } from "gridstack/dist/react";
    
    const options: GridStackOptions = {
      margin: 8,
      cellHeight: 50,
      column: 12,
      children: [
        { id: "1", x: 0, y: 0, w: 2, h: 2, content: "Plain HTML item" },
      ],
    };
    
    export function Board() {
      return <GridStack options={options} />;
    }
  7. Use Gridstack standalone components in Angular

    master

    For modern Angular applications, do not use GridstackModule. Instead, import GridstackComponent and GridstackItemComponent directly into your standalone components' imports array. This is the recommended approach for integrating Gridstack into Angular.

    // Preferred approach - standalone components
    @Component({
      selector: 'my-app',
      imports: [GridstackComponent, GridstackItemComponent],
      template: '<gridstack></gridstack>'
    })
    export class AppComponent {}
  8. Basic usage of gridstack.js

    master

    GridStack supports three main ways to create a dashboard layout:

    1. Dynamic creation: Use .addWidget() to add items via JavaScript.
    2. Loading from serialized data: Use .load() with an array of objects defining position (x, y) and size (w, h).
    3. DOM-based items: Define items directly in your HTML using the .grid-stack-item class and gs-* attributes.
    // 1. Dynamic creation
    var grid = GridStack.init();
    grid.addWidget({w: 2, content: 'item 1'});
    
    // 2. Loading from serialized data
    const serializedData = [
      {x: 0, y: 0, w: 2, h: 2},
      {x: 2, y: 3, w: 3, content: 'item 2'},
      {x: 1, y: 3}
    ];
    grid.load(serializedData);
    
    // 3. DOM created items
    // HTML: <div class="grid-stack"><div class="grid-stack-item" gs-w="2"><div class="grid-stack-item-content">Item 2</div></div></div>
    GridStack.init();
  9. Migrate from v3 to v4 (Collision and Drag Heuristics)

    master

    v4 introduced a complete rewrite of collision and drag-in/out heuristics.

    Breaking Changes:

    • Attribute Shortening: To improve efficiency, data- prefixes were removed and dimensions were shortened.
      • data-gs-min-width $\rightarrow$ gs-min-w
      • data-gs-width $\rightarrow$ gs-w
      • data-gs-height $\rightarrow$ gs-h
    • API Changes: GridStack.update(el, opt) now accepts a GridStackWidget object. Several wrapper methods like move(), resize(), locked(), maxWidth(), etc., are hidden in TypeScript as they are now wrappers for update(el, opt).
  10. Use GridstackComponent in Angular

    master

    The GridstackComponent is an Angular component wrapper for GridStack. It manages grid initialization, lifecycle, dynamic component creation, and event binding. It is intended to be used in combination with GridstackItemComponent for individual grid items.

    To use it, bind your GridStackOptions to the [options] input and listen to grid events using output bindings like (change).

    <gridstack [options="gridOptions" (change)="onGridChange($event)">
      <div empty-content>Drag widgets here</div
    </gridstack>
  11. Run the GridstackLib development server

    master
    To start the development server, use the Angular CLI command ng serve. Once running, you can access the application at http://localhost:4200/. The server supports hot-reloading, meaning the application will automatically reload when you modify source files.
    ng serve