1

I was able to get a working test chart using ChartJS but I'm having trouble with the Frappe Gantt library.

Right now it's throwing an error in the catch, but I think the error is null as I'm getting

Cannot read property 'message' of undefined

If I force it to call Initializechartjs(), I then get

Gantt is not defined

I can see all 4 resources loading -

resources

Here is my code

chart.html

<template>
    <lightning-card title="Gantt">
        <svg class="gantt" width="400" height="450" lwc:dom="manual"></svg>
    </lightning-card>
</template>

chart.js

import { LightningElement,api } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { loadScript, loadStyle } from 'lightning/platformResourceLoader';
import momentJS from '@salesforce/resourceUrl/momentJS';
import snapSVG from '@salesforce/resourceUrl/snapSVG';
import frappeGanttMin from '@salesforce/resourceUrl/frappeGanttMin';
import frappeGanttStyle from '@salesforce/resourceUrl/frappeGanttStyle';


 export default class Chartcmp extends LightningElement {
  @api chartjsInitialized = false;
   @api recordId;
   renderedCallback() {
        if (this.chartjsInitialized) {
          return;
         }
        this.chartjsInitialized = true;
        console.log('chart loading');
        Promise.all([
              loadScript(this, momentJS),
              loadScript(this, snapSVG),
              loadScript(this, frappeGanttMin),
              loadStyle(this, frappeGanttStyle)
        ])
    .then(() => {
        this.Initializechartjs();
    })
    .catch(error => {
        this.dispatchEvent(
            new ShowToastEvent({
                title: 'Error loading chart',
                message: error.message,
                variant: 'error'
            })
        );
    });
   }

  Initializechartjs() {
    console.log("loaded");
    //Get the context of the canvas element we want to select
    var chartClass = this.template.querySelector(".gantt");
    var gantt = new Gantt(chartClass ,{
        tasks: [
            {
                id: 'Task 1',
                name: 'Redesign website',
                start: '2016-12-28',
                end: '2016-12-31',
            },
            {
                id: 'Task 2',
                name: 'Second Task',
                start: '2016-12-29',
                end: '2016-12-30',
            }
        ]
    });

    }

}

3 Answers 3

0

You shouldn't fetch elements by ID in lwc, as per the documentation:

Don’t use ID selectors with querySelector. The IDs that you define in HTML templates may be transformed into globally unique values when the template is rendered. If you use an ID selector in JavaScript, it won’t match the transformed ID.

Also, it is very likely that frappeGanttMin is not supported (Locker Service)

instead of using frappeGanttMin , why not use a d3 Gant chart?

You can find some supported libraries in the following posts:

4
  • Changed to <svg class="gantt" lwc:dom="manual"></svg> and var svg = this.template.querySelector(".gantt"); Still getting the same errors.
    – Pete
    Commented Jun 30, 2019 at 21:29
  • please update your question =) and include the debug log (add a break point to see)
    – glls
    Commented Jun 30, 2019 at 21:32
  • @Pete => Gant is coming from "frappeGanttMin"? are you sure this library is supported?
    – glls
    Commented Jun 30, 2019 at 21:36
  • 1
    Yes, that's the static resource where I loaded the min.js file. Not sure if it's supported, how would I find out?
    – Pete
    Commented Jun 30, 2019 at 21:37
0

The loadScript, loadStyle don`t propagate the error up (they manually print it out as warning on console) which means in this case you are getting an undefined error object on which are trying to access the message property => which leads to the "Cannot read property 'message' of undefined" failure

Seems to be thrown by the snapSVG lib which is not running in lockerservice. the gant lib (while not throwing an error) will most likely not work due to lockerservice without modification. It assigns its functionality to a global scoped variable - which is not accessible. So you would need to manually modify it and assign it to the window object. (Which of course does not automatically mean its working - 3rd party always are trial and error ....)

Edit: First Glance I guess if you dont want to (potentially) rewrite much in the lib you can forget about it. The constructor expects a dom selector or svg element. If you pass a dom selector it will query it via document.queryselector which will not work in LWC. If you pass the svg element itself it will try to create wrapper elements and access the parent element - but in order for appendChild to work it requires the lwc:dom=manual directive which requires a empty parent element.. which means you could not pass a svg element. Manually creating the svg too in your cmp could work but i don`t know what other traps will wait in the lib.. so i guess you maybe want to search for alternative librarys

3
  • I removed snapSVG and the error message is Gantt is not defined. So it sounds like lockerservice is the issue.
    – Pete
    Commented Jun 30, 2019 at 23:03
  • see edit - if you didnt saw it yet. Getting the lib into the platform should work - if it will work then is a different question ;)
    – Renji-xD
    Commented Jun 30, 2019 at 23:05
  • thanks for the reply, much appreciated
    – Pete
    Commented Jul 1, 2019 at 0:49
0

If anyone still needs Frappe Gantt to work with LWC's, I have a modified version that works, wasn't able to get SnapSVG to load, but all other imports do: https://github.com/damianoda96/Frappe-Gantt-LWC

0

You must log in to answer this question.

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