Products
Intrasheets
LemonadeJS
MIT License
Jspreadsheet CE
MIT License
Jsuites
MIT License
JavaScript
JavaScript
React
VueJS
Angular
v10
v11
v10
v9
v8
v7

Data Grid Custom Cell Editor

The following example shows how to integrate a third-party plugin as a custom column.

Example

A basic integration with a third party component.

A custom column based on the clockpicker plugin by weareoutman.

<html>
<script src="https://jspreadsheet.com/v10/jspreadsheet.js"></script>
<script src="https://jsuites.net/v5/jsuites.js"></script>
<link rel="stylesheet" href="https://jspreadsheet.com/v10/jspreadsheet.css" type="text/css" />
<link rel="stylesheet" href="https://jsuites.net/v5/jsuites.css" type="text/css" />

<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Material+Icons" />

<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/clockpicker@0.0.7/dist/jquery-clockpicker.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/clockpicker@0.0.7/dist/jquery-clockpicker.min.js"></script>

<div id="custom"></div>

<script>
let clockEditor = function() {
    // Create the editor once to persist the whole lifecycle of the spreadsheet
    let editor = document.createElement('input');
    editor.classList.add('jss_object');
    editor.type = 'text';
    editor.style.width = '100%';

    // Close event
    let closeEvent = null;

    // Create instance of the clock picker
    $(editor).clockpicker({ afterDone: function() {
        closeEvent();
    }});

    // JSS editor
    let methods = {};

    methods.createCell = function(cell, value, x, y, instance, options) {
        cell.innerHTML = value;
    }

    methods.updateCell = function(cell, value, x, y, instance, options) {
        if (cell) {
            cell.innerHTML = value;
        }
    }

    methods.openEditor = function(cell, value, x, y, instance, options) {
        // Append the clock picker to the input container
        instance.parent.input.appendChild(editor);
        // Make sure input container is not editable
        instance.parent.input.setAttribute('contentEditable', false);
        // Set the current value
        editor.value = value;
        // Focus to open the clock picker
        editor.focus();
        // Make sure JSS object class is set to keep the focus on the spreadsheet
        if (! document.querySelector('.clockpicker-popover').classList.contains('jss_object')) {
            document.querySelector('.clockpicker-popover').classList.add('jss_object');
        }
        // Update close event
        closeEvent = function() {
            instance.closeEditor(cell, true);
        }
    }

    methods.closeEditor = function(cell, save, x, y, instance, options) {
        if (save) {
            cell.innerHTML = editor.value;
        } else {
            cell.innerHTML  = '';
        }
        // Return value
        return cell.innerHTML;
    }

    return methods;
}();

// Set your JSS license key (The following key only works for one day)
jspreadsheet.setLicense('ZWU0MjViZjg1NjMwMjczN2IyOGZmMjVjN2FjYTcwMGM3OWY5ZTg3ZGFmMjk2NjViMGEwYjg5MGVhYjNmZmJlMDU0OGU3NWU3MjY1NjI2MGY5MzBiNzA5Y2ZmMDdjMGM2YmM4ZjhhOWQ2NDUwODcwNzkzNmU4MzNhOTQ5Zjc5NzgsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpNMk5EYzRPVEUyTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0ozWldJaUxDSnNiMk5oYkdodmMzUWlYU3dpY0d4aGJpSTZJak0wSWl3aWMyTnZjR1VpT2xzaWRqY2lMQ0oyT0NJc0luWTVJaXdpZGpFd0lpd2lkakV4SWl3aVkyaGhjblJ6SWl3aVptOXliWE1pTENKbWIzSnRkV3hoSWl3aWNHRnljMlZ5SWl3aWNtVnVaR1Z5SWl3aVkyOXRiV1Z1ZEhNaUxDSnBiWEJ2Y25SbGNpSXNJbUpoY2lJc0luWmhiR2xrWVhScGIyNXpJaXdpYzJWaGNtTm9JaXdpY0hKcGJuUWlMQ0p6YUdWbGRITWlMQ0pqYkdsbGJuUWlMQ0p6WlhKMlpYSWlMQ0p6YUdGd1pYTWlYU3dpWkdWdGJ5STZkSEoxWlgwPQ==');

// Create the spreadsheet
jspreadsheet(document.getElementById('custom'), {
    worksheets: [{
        data: [
            ['PHP', '14:00'],
            ['Javascript', '16:30'],
        ],
        columns: [
            {
                type: 'text',
                title: 'Course Title',
                width: '300px'
            },
            {
                type: clockEditor,
                title: 'Time',
                width: '200px'
            },
         ]
    }]
});
</script>
</html>
import React, { useRef } from "react";
import { createRoot } from "react-dom";
import { Spreadsheet, Worksheet, jspreadsheet } from "@jspreadsheet/react";
import Switch from "@mui/material/Switch";

const license = 'ZWU0MjViZjg1NjMwMjczN2IyOGZmMjVjN2FjYTcwMGM3OWY5ZTg3ZGFmMjk2NjViMGEwYjg5MGVhYjNmZmJlMDU0OGU3NWU3MjY1NjI2MGY5MzBiNzA5Y2ZmMDdjMGM2YmM4ZjhhOWQ2NDUwODcwNzkzNmU4MzNhOTQ5Zjc5NzgsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpNMk5EYzRPVEUyTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0ozWldJaUxDSnNiMk5oYkdodmMzUWlYU3dpY0d4aGJpSTZJak0wSWl3aWMyTnZjR1VpT2xzaWRqY2lMQ0oyT0NJc0luWTVJaXdpZGpFd0lpd2lkakV4SWl3aVkyaGhjblJ6SWl3aVptOXliWE1pTENKbWIzSnRkV3hoSWl3aWNHRnljMlZ5SWl3aWNtVnVaR1Z5SWl3aVkyOXRiV1Z1ZEhNaUxDSnBiWEJ2Y25SbGNpSXNJbUpoY2lJc0luWmhiR2xrWVhScGIyNXpJaXdpYzJWaGNtTm9JaXdpY0hKcGJuUWlMQ0p6YUdWbGRITWlMQ0pqYkdsbGJuUWlMQ0p6WlhKMlpYSWlMQ0p6YUdGd1pYTWlYU3dpWkdWdGJ5STZkSEoxWlgwPQ==';

const Editor = {
    createCell: (cell, value, x, y, instance, options) => {
        // Clone the column definitions
        let o = { ...options, defaultChecked: !!value };
        // type is a reserved property
        delete o.type;
        // Change handler
        const onChange = function (event, newValue) {
            // Update the JSS data based on the component
            instance.setValue(cell, newValue);
        };
        // Create the link between react component and JSS
        createRoot(cell).render(<Switch {...o} onChange={onChange} />);
    },
    updateCell: (cell, value) => {
        // Get the checkbox
        let input = cell.querySelector("input");
        // Toggle the value
        input.checked = !!value;
    },
    openEditor: (cell, value, x, y, instance) => {
        // Toggle the value
        instance.setValue(cell, !value);
        // Do not open editor since is just a checkbox
        return false;
    },
    closeEditor: () => {
        // This is not used
        return false;
    }
};

export default function App() {
    // Spreadsheet array of worksheets
    const spreadsheet = useRef();
    // Data
    const data = [[true]];
    // Columns
    const columns = [
        {
            type: Editor,
            color: "warning"
        }
    ];

    // Render component
    return (
        <Spreadsheet ref={spreadsheet} license={license}>
            <Worksheet data={data} columns={columns} />
        </Spreadsheet>
    );
}