[SalesForce] Handsontable 3rd party library not working in LWC

Handsontable is a neat looking spreadsheet plugin for Javascript. I can't get even the quick start to display in an LWC component. It seems to initialize but the data never shows up. As far as I can tell, I'm following the 3rd party library instructions for LWC. I've looked through the Handsontable docs, worked with support and a common solution is to call render() after a timeout. I tried 150ms, 300ms, 5000ms but that doesn't seem to make a difference. I don't see any errors, just a rendered empty table in the source. Can anyone assist? I'm happy with any spreadsheet type grid if there's one you have working.

Here's where I am:

  1. Use the Handsontable quick start as the target goal: https://handsontable.com/docs/7.1.0/tutorial-quick-start.html
  2. Download LWC Recipes – my code is modeled very carefully after the libsD3 example seen here https://github.com/trailheadapps/lwc-recipes/tree/master/force-app/main/default/lwc/libsD3
  3. Modify the 3rd party library examples and make a new libsSheet LWC component
  4. Uploaded handsontable Vanilla JS zip file as a static resource (label: "handsontable")
  5. Wrote this code:
<!-- libsSheet.html -->
<template>
    <lightning-card title="My Sheet" icon-name="custom:custom19">
        <div class="slds-m-around_medium">
            <div id="hot" class="hot" lwc:dom="manual" style="height:300px;width:800px;"></div>
        </div>
    </lightning-card>
</template>
//libsSheet.js
import { LightningElement, track,api } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { loadScript, loadStyle } from 'lightning/platformResourceLoader';
import hands from '@salesforce/resourceUrl/handsontable';

export default class LibsSheet extends LightningElement {
    sheetInitialized = false;
    renderedCallback() {
        if (this.sheetInitialized) {
            return;
        }
        this.sheetInitialized = true;

        Promise.all([
            loadScript(this, hands + '/handsontable-master/dist/handsontable.full.min.js'),
            loadStyle(this, hands + '/handsontable-master/dist/handsontable.full.min.css')
        ]).then(() => {
            this.initializeSheet();
    })
    .catch(error => {
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Error loading Sheets',
                    message: error.message,
                    variant: 'error'
                })
            );
    });
    }

    initializeSheet() {
        var cmp = this.template.querySelector('.hot');
        var data =  [
                ['', 'Maserati', 'Mazda', 'Mercedes', 'Mini', 'Mitsubishi'],
                ['2009', 0, 2941, 4303, 354, 5814],
                ['2010', 3, 2905, 2867, 412, 5284],
                ['2011', 4, 2517, 4822, 552, 6127],
                ['2012', 2, 2422, 5399, 776, 4151]
            ];

        this.hsheet = new Handsontable(cmp, {
            data: data,
            colHeaders: true,
            rowHeaders: true,
            contextMenu: true,
            licenseKey: 'non-commercial-and-evaluation'

        });

        setTimeout(() => {
            this.hsheet.render();
        },1000);
    }
}
<!-- libsSheet.js-meta.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>46.0</apiVersion>
<description>Libs Sheet</description>
<masterLabel>Libs Sheet</masterLabel>
<isExposed>true</isExposed>
<targets>
    <target>lightning__AppPage</target>
    <target>lightning__RecordPage</target>
    <target>lightning__HomePage</target>
</targets>
</LightningComponentBundle>

Best Answer

This library is trying to break out of the shadow dom which is prevented by lockerservice. So i would consider it as non LWC Compliant which means only available in aura (could still fail due to lockerservice on a different line) or lockerservice workarounds like aura component max version 39, lightning:container app or iframed vf page

Related Topic