Demo

Interactive Data Grid

This demo showcases the power of LemonadeJS data-grid plugin to create fully reactive, editable tables with built-in features like search, pagination, and real-time data binding.


<html>
<script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@lemonadejs/data-grid/dist/index.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lemonadejs/data-grid/dist/style.min.css" />

<div id="root"></div>

<script>
function DataGridDemo() {
    const self = this;

    // Sample data with more fields
    self.data = [
        { id: 1, name: "John Doe", email: "john@example.com", role: "Developer", department: "Engineering", salary: "$95,000", status: "Active", joined: "2022-03-15" },
        { id: 2, name: "Jane Smith", email: "jane@example.com", role: "Designer", department: "Design", salary: "$85,000", status: "Active", joined: "2021-08-22" },
        { id: 3, name: "Bob Johnson", email: "bob@example.com", role: "Manager", department: "Operations", salary: "$105,000", status: "Inactive", joined: "2020-01-10" },
        { id: 4, name: "Alice Williams", email: "alice@example.com", role: "Developer", department: "Engineering", salary: "$92,000", status: "Active", joined: "2023-05-18" },
        { id: 5, name: "Charlie Brown", email: "charlie@example.com", role: "QA Engineer", department: "Quality", salary: "$78,000", status: "Active", joined: "2022-11-05" },
        { id: 6, name: "Diana Prince", email: "diana@example.com", role: "Product Owner", department: "Product", salary: "$110,000", status: "Active", joined: "2021-02-14" },
        { id: 7, name: "Eve Martinez", email: "eve@example.com", role: "Developer", department: "Engineering", salary: "$88,000", status: "Inactive", joined: "2023-09-30" },
        { id: 8, name: "Frank Castle", email: "frank@example.com", role: "DevOps", department: "Engineering", salary: "$98,000", status: "Active", joined: "2022-07-12" },
        { id: 9, name: "Grace Lee", email: "grace@example.com", role: "Designer", department: "Design", salary: "$82,000", status: "Active", joined: "2023-01-20" },
        { id: 10, name: "Henry Ford", email: "henry@example.com", role: "Manager", department: "Sales", salary: "$115,000", status: "Active", joined: "2020-06-08" },
    ];

    // Enhanced grid configuration with custom rendering
    self.columns = [
        {
            name: 'id',
            title: 'ID',
            width: '60px',
            align: 'center'
        },
        {
            name: 'name',
            title: 'Name',
            width: '150px',
            align: 'center',
            render: function(value) {
                return '<strong>' + value + '</strong>';
            }
        },
        {
            name: 'email',
            title: 'Email',
            width: '200px',
            align: 'center'
        },
        {
            name: 'role',
            title: 'Role',
            width: '130px',
            align: 'center'
        },
        {
            name: 'department',
            title: 'Department',
            width: '120px',
            align: 'center'
        },
        {
            name: 'salary',
            title: 'Salary',
            width: '100px',
            align: 'center'
        },
        {
            name: 'status',
            title: 'Status',
            width: '100px',
            align: 'center',
            render: function(value) {
                const color = value === 'Active' ? '#22c55e' : '#ef4444';
                return '<span style="color: ' + color + '; font-weight: 600;">' + value + '</span>';
            }
        },
        {
            name: 'joined',
            title: 'Joined Date',
            width: '110px',
            align: 'center'
        }
    ];

    self.gridRef = null;
    self.updateTrigger = 0;

    self.onUpdate = function(instance, cell, x, y, value) {
        // Force reactivity by updating trigger
        self.updateTrigger++;
    };

    self.addEmployee = function() {
        const newId = self.data.length + 1;
        self.data = [...self.data, {
            id: newId,
            name: "New Employee",
            email: "new@example.com",
            role: "Developer",
            department: "Engineering",
            salary: "$80,000",
            status: "Active",
            joined: new Date().toISOString().split('T')[0]
        }];
        self.updateTrigger++;
    };

    self.removeSelected = function() {
        if (self.data.length > 0) {
            self.data = self.data.slice(0, -1);
            self.updateTrigger++;
        }
    };

    self.getActiveCount = function() {
        return self.data.filter(emp => emp.status === 'Active').length;
    };

    return `<div style="padding: 20px;">
        <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">
            <h3 style="margin: 0;">Employee Management System</h3>
            <div style="display: flex; gap: 10px;">
                <button onclick="self.addEmployee()" class="button primary">Add Employee</button>
                <button onclick="self.removeSelected()" class="button">Remove Last</button>
            </div>
        </div>
        <p style="margin: 0 0 16px 0; font-size: 13px; color: #64748b;"><em>💡 Tip: Double-click any cell to edit. Try changing the Status to "Active" or "Inactive"</em></p>

        <DataGrid
            :ref="self.gridRef"
            :data="self.data"
            :columns="self.columns"
            search="true"
            pagination="5"
            editable="true"
            resizable="true"
            :onupdate="self.onUpdate" />

        <div style="margin-top: 25px; padding: 20px; background: #f8fafc; border-radius: 8px; display: flex; gap: 30px;">
            <div>
                <h4 style="margin: 0 0 8px 0; font-size: 14px; color: #64748b;">Total Employees</h4>
                <p style="margin: 0; font-size: 24px; font-weight: 700; color: #1e293b;">{{self.updateTrigger >= 0 ? self.data.length : 0}}</p>
            </div>
            <div>
                <h4 style="margin: 0 0 8px 0; font-size: 14px; color: #64748b;">Active Employees</h4>
                <p style="margin: 0; font-size: 24px; font-weight: 700; color: #22c55e;">{{self.updateTrigger >= 0 ? self.getActiveCount() : 0}}</p>
            </div>
            <div>
                <h4 style="margin: 0 0 8px 0; font-size: 14px; color: #64748b;">Inactive Employees</h4>
                <p style="margin: 0; font-size: 24px; font-weight: 700; color: #ef4444;">{{self.updateTrigger >= 0 ? (self.data.length - self.getActiveCount()) : 0}}</p>
            </div>
        </div>
    </div>`;
}

lemonade.render(DataGridDemo, document.getElementById('root'));
</script>
</html>
import lemonade from 'lemonadejs';
import Datagrid from '@lemonadejs/data-grid';
import '@lemonadejs/data-grid/dist/style.min.css';

export default function DataGridDemo() {
    const self = this;

    // Sample data with more fields
    self.data = [
        { id: 1, name: "John Doe", email: "john@example.com", role: "Developer", department: "Engineering", salary: "$95,000", status: "Active", joined: "2022-03-15" },
        { id: 2, name: "Jane Smith", email: "jane@example.com", role: "Designer", department: "Design", salary: "$85,000", status: "Active", joined: "2021-08-22" },
        { id: 3, name: "Bob Johnson", email: "bob@example.com", role: "Manager", department: "Operations", salary: "$105,000", status: "Inactive", joined: "2020-01-10" },
        { id: 4, name: "Alice Williams", email: "alice@example.com", role: "Developer", department: "Engineering", salary: "$92,000", status: "Active", joined: "2023-05-18" },
        { id: 5, name: "Charlie Brown", email: "charlie@example.com", role: "QA Engineer", department: "Quality", salary: "$78,000", status: "Active", joined: "2022-11-05" },
        { id: 6, name: "Diana Prince", email: "diana@example.com", role: "Product Owner", department: "Product", salary: "$110,000", status: "Active", joined: "2021-02-14" },
        { id: 7, name: "Eve Martinez", email: "eve@example.com", role: "Developer", department: "Engineering", salary: "$88,000", status: "Inactive", joined: "2023-09-30" },
        { id: 8, name: "Frank Castle", email: "frank@example.com", role: "DevOps", department: "Engineering", salary: "$98,000", status: "Active", joined: "2022-07-12" },
        { id: 9, name: "Grace Lee", email: "grace@example.com", role: "Designer", department: "Design", salary: "$82,000", status: "Active", joined: "2023-01-20" },
        { id: 10, name: "Henry Ford", email: "henry@example.com", role: "Manager", department: "Sales", salary: "$115,000", status: "Active", joined: "2020-06-08" },
    ];

    // Enhanced grid configuration
    self.columns = [
        { name: 'id', title: 'ID', width: '60px', align: 'center' },
        { name: 'name', title: 'Name', width: '150px', align: 'center', render: (v) => `<strong>${v}</strong>` },
        { name: 'email', title: 'Email', width: '200px', align: 'center' },
        { name: 'role', title: 'Role', width: '130px', align: 'center' },
        { name: 'department', title: 'Department', width: '120px', align: 'center' },
        { name: 'salary', title: 'Salary', width: '100px', align: 'center' },
        {
            name: 'status',
            title: 'Status',
            width: '100px',
            align: 'center',
            render: (v) => {
                const color = v === 'Active' ? '#22c55e' : '#ef4444';
                return `<span style="color: ${color}; font-weight: 600;">${v}</span>`;
            }
        },
        { name: 'joined', title: 'Joined Date', width: '110px', align: 'center' }
    ];

    self.updateTrigger = 0;

    self.onUpdate = (instance, cell, x, y, value) => {
        self.updateTrigger++;
    };

    self.addEmployee = () => {
        self.data = [...self.data, {
            id: self.data.length + 1,
            name: "New Employee",
            email: "new@example.com",
            role: "Developer",
            department: "Engineering",
            salary: "$80,000",
            status: "Active",
            joined: new Date().toISOString().split('T')[0]
        }];
        self.updateTrigger++;
    };

    self.removeSelected = () => {
        if (self.data.length > 0) {
            self.data = self.data.slice(0, -1);
            self.updateTrigger++;
        }
    };

    self.getActiveCount = () => self.data.filter(emp => emp.status === 'Active').length;

    return `<div style="padding: 20px;">
        <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">
            <h3 style="margin: 0;">Employee Management System</h3>
            <div style="display: flex; gap: 10px;">
                <button onclick="self.addEmployee()" class="button primary">Add Employee</button>
                <button onclick="self.removeSelected()" class="button">Remove Last</button>
            </div>
        </div>
        <p style="margin: 0 0 16px 0; font-size: 13px; color: #64748b;"><em>💡 Tip: Double-click any cell to edit. Try changing the Status to "Active" or "Inactive"</em></p>
        <DataGrid :data="self.data" :columns="self.columns" search="true" pagination="5" editable="true" resizable="true" :onupdate="self.onUpdate" />
        <div style="margin-top: 25px; padding: 20px; background: #f8fafc; border-radius: 8px; display: flex; gap: 30px;">
            <div>
                <h4 style="margin: 0 0 8px 0; font-size: 14px; color: #64748b;">Total Employees</h4>
                <p style="margin: 0; font-size: 24px; font-weight: 700; color: #1e293b;">{{self.updateTrigger >= 0 ? self.data.length : 0}}</p>
            </div>
            <div>
                <h4 style="margin: 0 0 8px 0; font-size: 14px; color: #64748b;">Active Employees</h4>
                <p style="margin: 0; font-size: 24px; font-weight: 700; color: #22c55e;">{{self.updateTrigger >= 0 ? self.getActiveCount() : 0}}</p>
            </div>
            <div>
                <h4 style="margin: 0 0 8px 0; font-size: 14px; color: #64748b;">Inactive Employees</h4>
                <p style="margin: 0; font-size: 24px; font-weight: 700; color: #ef4444;">{{self.updateTrigger >= 0 ? (self.data.length - self.getActiveCount()) : 0}}</p>
            </div>
        </div>
    </div>`;
}
import React, { useState } from 'react';
import { DataGrid } from '@lemonadejs/data-grid/react';
import '@lemonadejs/data-grid/dist/style.min.css';

export default function DataGridDemo() {
    const [data, setData] = useState([
        { id: 1, name: "John Doe", email: "john@example.com", role: "Developer", department: "Engineering", salary: "$95,000", status: "Active", joined: "2022-03-15" },
        { id: 2, name: "Jane Smith", email: "jane@example.com", role: "Designer", department: "Design", salary: "$85,000", status: "Active", joined: "2021-08-22" },
        { id: 3, name: "Bob Johnson", email: "bob@example.com", role: "Manager", department: "Operations", salary: "$105,000", status: "Inactive", joined: "2020-01-10" },
        { id: 4, name: "Alice Williams", email: "alice@example.com", role: "Developer", department: "Engineering", salary: "$92,000", status: "Active", joined: "2023-05-18" },
        { id: 5, name: "Charlie Brown", email: "charlie@example.com", role: "QA Engineer", department: "Quality", salary: "$78,000", status: "Active", joined: "2022-11-05" },
        { id: 6, name: "Diana Prince", email: "diana@example.com", role: "Product Owner", department: "Product", salary: "$110,000", status: "Active", joined: "2021-02-14" },
        { id: 7, name: "Eve Martinez", email: "eve@example.com", role: "Developer", department: "Engineering", salary: "$88,000", status: "Inactive", joined: "2023-09-30" },
        { id: 8, name: "Frank Castle", email: "frank@example.com", role: "DevOps", department: "Engineering", salary: "$98,000", status: "Active", joined: "2022-07-12" },
        { id: 9, name: "Grace Lee", email: "grace@example.com", role: "Designer", department: "Design", salary: "$82,000", status: "Active", joined: "2023-01-20" },
        { id: 10, name: "Henry Ford", email: "henry@example.com", role: "Manager", department: "Sales", salary: "$115,000", status: "Active", joined: "2020-06-08" },
    ]);

    const columns = [
        { name: 'id', title: 'ID', width: '60px', align: 'center' },
        { name: 'name', title: 'Name', width: '150px', align: 'center', render: (v) => `<strong>${v}</strong>` },
        { name: 'email', title: 'Email', width: '200px', align: 'center' },
        { name: 'role', title: 'Role', width: '130px', align: 'center' },
        { name: 'department', title: 'Department', width: '120px', align: 'center' },
        { name: 'salary', title: 'Salary', width: '100px', align: 'center' },
        {
            name: 'status',
            title: 'Status',
            width: '100px',
            align: 'center',
            render: (v) => {
                const color = v === 'Active' ? '#22c55e' : '#ef4444';
                return `<span style="color: ${color}; font-weight: 600;">${v}</span>`;
            }
        },
        { name: 'joined', title: 'Joined Date', width: '110px', align: 'center' }
    ];

    const onUpdate = (instance, cell, x, y, value) => {
        setData([...data]);
    };

    const addEmployee = () => {
        setData([...data, {
            id: data.length + 1,
            name: "New Employee",
            email: "new@example.com",
            role: "Developer",
            department: "Engineering",
            salary: "$80,000",
            status: "Active",
            joined: new Date().toISOString().split('T')[0]
        }]);
    };

    const removeSelected = () => {
        if (data.length > 0) {
            setData(data.slice(0, -1));
        }
    };

    const getActiveCount = () => data.filter(emp => emp.status === 'Active').length;

    return (
        <div style={{ padding: '20px' }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '8px' }}>
                <h3 style={{ margin: 0 }}>Employee Management System</h3>
                <div style={{ display: 'flex', gap: '10px' }}>
                    <button onClick={addEmployee} className="button primary">Add Employee</button>
                    <button onClick={removeSelected} className="button">Remove Last</button>
                </div>
            </div>
            <p style={{ margin: '0 0 16px 0', fontSize: '13px', color: '#64748b' }}><em>💡 Tip: Double-click any cell to edit. Try changing the Status to "Active" or "Inactive"</em></p>
            <DataGrid
                data={data}
                columns={columns}
                search={true}
                pagination={5}
                editable={true}
                resizable={true}
                onupdate={onUpdate}
            />
            <div style={{ marginTop: '25px', padding: '20px', background: '#f8fafc', borderRadius: '8px', display: 'flex', gap: '30px' }}>
                <div>
                    <h4 style={{ margin: '0 0 8px 0', fontSize: '14px', color: '#64748b' }}>Total Employees</h4>
                    <p style={{ margin: 0, fontSize: '24px', fontWeight: 700, color: '#1e293b' }}>{data.length}</p>
                </div>
                <div>
                    <h4 style={{ margin: '0 0 8px 0', fontSize: '14px', color: '#64748b' }}>Active Employees</h4>
                    <p style={{ margin: 0, fontSize: '24px', fontWeight: 700, color: '#22c55e' }}>{getActiveCount()}</p>
                </div>
                <div>
                    <h4 style={{ margin: '0 0 8px 0', fontSize: '14px', color: '#64748b' }}>Inactive Employees</h4>
                    <p style={{ margin: 0, fontSize: '24px', fontWeight: 700, color: '#ef4444' }}>{data.length - getActiveCount()}</p>
                </div>
            </div>
        </div>
    );
}
<template>
    <div>
        <h3>Employee Management</h3>
        <DataGrid
            :data="data"
            :columns="columns"
            :search="true"
            :pagination="4"
        />

        <div style="margin-top: 20px;">
            <h4>Live Data Preview:</h4>
            <p>Total Employees: {{ data.length }}</p>
        </div>
    </div>
</template>

<script>
import { DataGrid } from '@lemonadejs/data-grid/vue';
import '@lemonadejs/data-grid/dist/style.min.css';

export default {
    name: 'DataGridDemo',
    components: {
        DataGrid
    },
    data() {
        return {
            data: [
                { name: "John Doe", email: "john@example.com", role: "Developer", status: "Active" },
                { name: "Jane Smith", email: "jane@example.com", role: "Designer", status: "Active" },
                { name: "Bob Johnson", email: "bob@example.com", role: "Manager", status: "Inactive" },
                { name: "Alice Williams", email: "alice@example.com", role: "Developer", status: "Active" },
                { name: "Charlie Brown", email: "charlie@example.com", role: "QA Engineer", status: "Active" },
                { name: "Diana Prince", email: "diana@example.com", role: "Product Owner", status: "Active" },
                { name: "Eve Martinez", email: "eve@example.com", role: "Developer", status: "Inactive" },
                { name: "Frank Castle", email: "frank@example.com", role: "DevOps", status: "Active" },
            ],
            columns: [
                { name: 'name', title: 'Name', width: '150px' },
                { name: 'email', title: 'Email', width: '200px' },
                { name: 'role', title: 'Role', width: '150px' },
                { name: 'status', title: 'Status', width: '100px' },
            ]
        }
    }
}
</script>