5

I'm trying out the Light DOM beta as I want to see how it will work with certain 3rd party libraries, but I cannot load a 3rd party javascript resource. I have the following component on a Salesforce (internal) record page:

// outer component - shadow dom
<template>
  <c-inner-component record-id={recordId}></c-inner-component>
</template>
// inner component - light dom
<template lwc:render-mode='light'>
  <table class="slds-table slds-table_cell-buffer slds-table_bordered slds-table_striped print-target" >
  // ...
  </table>
</template>
// inner component js
import { LightningElement, api, wire, track } from "lwc";
import { loadScript } from "lightning/platformResourceLoader";
import { NavigationMixin, CurrentPageReference } from "lightning/navigation";

export default class InnerComponent extends NavigationMixin(LightningElement) {
    static renderMode = 'light';
    @api recordId;

    // ...
}

Up to this point, everything is ok; the component loads and renders. Note that per the Light DOM docs, I have added lwc:render-mode='light' to my top-level template and static renderMode = 'light'; to my JS class. I also updated one use of this.template.querySelector to this.querySelector, but that's irrelevant to the issue, as that code never executes (it is triggered by a button). I have also wrapped my Light DOM component (inner-component) in a Shadow DOM component (outer component) as outlined in this knowledge article.

Now I want to load a 3rd party library which I have stored in a static resource. So I add this:

// before class declaration
import jsPdf from '@salesforce/resourceUrl/jspdf';

// inside class
    renderedCallback() {
        if (this.jsPdfInitialized) {
            return;
        }
        this.jsPdfInitialized = true;
        Promise.all([
            loadScript(this, jsPdf)
        ]);
    }

At which point, reloading the page gives the error

Invariant violation: Expected template to be an object

with the stack trace:

TypeError: Invariant violation: Expected template to be an object
    at Pf (https://orgname--orgname.lightning.force.com/auraFW/javascript/20g2uYzAuTpaB3EECmeKLg/aura_prod.js:65:64332)
    at tp (https://orgname--orgname.lightning.force.com/auraFW/javascript/20g2uYzAuTpaB3EECmeKLg/aura_prod.js:65:68175)
    at Ie.get [as template] (https://orgname--orgname.lightning.force.com/auraFW/javascript/20g2uYzAuTpaB3EECmeKLg/aura_prod.js:65:72525)
    at t (https://orgname--orgname.lightning.force.com/components/lightning/platformResourceLoader.js:1:191)
    at e.loadScript (https://orgname--orgname.lightning.force.com/components/lightning/platformResourceLoader.js:1:488)
    at Ie.renderedCallback (https://orgname--orgname.lightning.force.com/lightning/r/Account/0015a00002fPp7LAAS/modules/c/innerComponent.js:1:6574)
    at callHook (https://orgname--orgname.lightning.force.com/auraFW/javascript/20g2uYzAuTpaB3EECmeKLg/aura_prod.js:65:72035)
    at https://orgname--orgname.lightning.force.com/auraFW/javascript/20g2uYzAuTpaB3EECmeKLg/aura_prod.js:13:31075
    at ar (https://orgname--orgname.lightning.force.com/auraFW/javascript/20g2uYzAuTpaB3EECmeKLg/aura_prod.js:13:35571)
    at Po (https://orgname--orgname.lightning.force.com/auraFW/javascript/20g2uYzAuTpaB3EECmeKLg/aura_prod.js:13:31060)

I have tried changing which library I load (I have html2canvas stored as a static resource as well, as I may want to use it), but it doesn't matter. And note that no code is calling the loaded script; I'm just loading it. But I can find no way to load the library if Light DOM is enabled in my component.

3
  • I don't think light dom is really ready yet. Commented Jun 23, 2022 at 21:56
  • 1
    @CasparHarmer So far I'd have to agree :) But that's what a Beta is for, and light dom is supposed to help "ease third-party integrations", so it seems like a valid test case. I'm hoping someone else has tried this. I may try a partner case as well. Commented Jun 23, 2022 at 21:59
  • 1
    I tried to use it... I had several errors that seemed to have no resolution (I forget what they were). I've put aside for a bit. VS Code Plugin also unable to handle the light dom syntax in it's markup parser. At this point, I'd say it's really an alpha release. Commented Jun 24, 2022 at 0:27

3 Answers 3

3

I have gotten this working (using Chart.js), but it requires a bit of a different approach.

I had to add the Chart.js script as a static resource (due to CSP). As the loadScript method does NOT work - the script needed to be loaded via a <script> tag:

import CHART_JS from "@salesforce/resourceUrl/Chart_js"
renderedCallback() {
    try {
        if (this.scriptTagCreated === false) {
            const tag = document.createElement("script");
            tag.src = CHART_JS + "/chart.min.js";
            tag.type = "text/javascript";
            tag.onload = () => {
                this.scriptLoaded = true;
                if (this._chartConfiguration !== undefined) {
                    this.createChart();
                    this.chartCreated = true;
                }
            };
            this.querySelector('[data-id="script"]').appendChild(tag);
            this.scriptTagCreated = true;
        }
    } catch (ex) {
        //Do something here
    }
}

There is one final issue that you may encounter - and that is ResizeObserver is not a constructor.

This issue is due to ResizeObserver not being supported by the LockerService.

To get around this - turn off responsiveness in the chart config - and implement your own as follows:

createChart() {
    const element = this.querySelector('[data-id="chart"]');
    const config = deepClone(this._chartConfiguration);
    //Ensure that the responsiveness is disabled as ResizeObserver
    //is not supported by the LockerService
    if (!config.options) {
        config.options = {
            responsive: false
        };
    } else {
        config.options.responsive = false;
    }
    this.chartInstance = new Chart(
        element.getContext("2d"),
        config
    );
    this.chartInstance.resize();
}

connectedCallback() {
    try {
        window.addEventListener(
            "resize",
            this.handleWindowResize
        );
    } catch (ex) {
        //Handle this
    }
}

disconnectedCallback() {
    try {
        window.removeEventListener(
            "resize",
            this.handleWindowResize
        );
    } catch (ex) {
        //Handle this
    }
}

handleWindowResize = () => {
    if (this.chartCreated === true) {
        this.chartInstance.resize();
    }
}

Documentation for Chart.js responsiveness: https://www.chartjs.org/docs/latest/configuration/responsive.html

2
  • Hi @Nic. I have tried following above. However I am facing issues with chart if the number of records/bars go beyond 1600 in which case the bars overlap. Is there any limitation with number of records. I have posted the code here if you can kindly review. salesforce.stackexchange.com/questions/415812/…
    – starhunter
    Commented Jan 16 at 17:05
  • Hey @starhunter, that definitely looks like some of the issues I've seen from CSS problems - but I was working with much smaller data sets and this could very well be different. I'd first inspect with the browser and check whether there is any max-height, etc. that could block the chart. It could also be to a discrepancy in the data, which I certainly struggled with :). Failing that, I'd suggest hitting up github.com/chartjs/Chart.js and making an issue there if one doesn't already exist. Commented Jan 18 at 13:57
1

A partial answer - I've found (in a W'23 preview org) that enabling Lighting Web Security makes this error go away. I'm still having issues getting the library to work, as it wants to modify the DOM (which I thought light DOM could allow?), but that's a different issue.

If you just need to load a JS Lib under light DOM, Lightning Web Security may allow it.

1

This should be fixed in Summer'23 release.

2
  • 1
    Is it fixed or upcoming? Commented Oct 20, 2023 at 15:44
  • Summer'23 is already released. It should be fixed. Commented Nov 30, 2023 at 21:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .