Using Google Chart in Javascript Web Component

Viewed 63

I want to encapsulate a Gantt Chart using Google Charts as a web component.

Unfortunately I get the error "TypeError: google.visualization.Gantt is not a constructor".

I tested to switch the initializing of the google objects from the constructor to the connectedFallback to ensure the web component DOM exists, but that was no solution.

Maybe the scope is the issue (google.visualization.Gantt does not work in ES6 class?).

Here is my web component (file: GanttChart.js):

// Using Google Charts: https://developers.google.com/chart/interactive/docs/gallery/ganttchart

// Using Google Charts: https://developers.google.com/chart/interactive/docs/gallery/ganttchart

class GanttChart extends HTMLElement {
    
    // @para columns: array with objects { type, name }. type can be string, date, number.
    // @ para model: model.data must be array.
    constructor(columns=[], model={}, options={}){
        super();
        
        this.columns = columns;
        this.model = model;
        this.options = options;
        
        this.root = this.attachShadow({ mode: "open" });
        this.root.appendChild(this.template.content.cloneNode(true));
    }
    
    get template(){
        let template = document.createElement("template");
        
        template.content.appendChild(document.createElement("div"));

        return template;
    }
    
    renderGoogleChartScript(){
        let script = document.createElement("script");
        script.type = "text/javascript";
        script.src = "https://www.gstatic.com/charts/loader.js";
        script.onload = this.init;
        
        return script;
    }
        
    init(){
        console.log("[https://www.gstatic.com/charts/loader.js] is loaded. Initializing gantt chart...");
        google.charts.load('current', {'packages':['gantt']});
        google.charts.setOnLoadCallback(this.render);
    }
        
    get div(){
        return this.root.querySelector("div");
    }
    
    connectedCallback() {
        console.log("GanttChart connected");
        document.head.appendChild(this.renderGoogleChartScript());
  }

    render = () => {
        console.log("Rendering...");
        
        let data = new google.visualization.DataTable();
        
        this.columns.forEach(col => data.addColumn(col));
        this.model.data.forEach(item => data.addRow(item));
        
        let chart = new google.visualization.Gantt(this.div);
    chart.draw(data, this.options);
    }

  disconnectedCallback() {
    
  }

  static get observedAttributes() {
    return [
            
        ];
  }

  attributeChangedCallback(name, oldValue, newValue) {
    if(oldValue === newValue) return;
        
        
  }

  adoptedCallback() {
    
  }
    
    setEventHandlers(){
        this.model.on("changed", this.render);
    }
            

}

window.customElements.define("gantt-chart", GanttChart);

Chrome debug console:

GanttChart connected
GanttChart.js:47 GanttChart connected
2GanttChart.js:37 [https://www.gstatic.com/charts/loader.js] is loaded. Initializing gantt chart...
VM1057 jsapi_compiled_ui_module.js:315 Uncaught TypeError: this.qa.set is not a function
    at gvjs_.set (VM1057 jsapi_compiled_ui_module.js:315:423)
    at gvjs_.set (VM1057 jsapi_compiled_ui_module.js:343:179)
    at gvjs_.Pi (VM1057 jsapi_compiled_ui_module.js:343:274)
    at VM1057 jsapi_compiled_ui_module.js:345:269
gvjs_.set @ VM1057 jsapi_compiled_ui_module.js:315
gvjs_.set @ VM1057 jsapi_compiled_ui_module.js:343
gvjs_.Pi @ VM1057 jsapi_compiled_ui_module.js:343
(anonymous) @ VM1057 jsapi_compiled_ui_module.js:345
VM1060 jsapi_compiled_gantt_module.js:4 Uncaught TypeError: Cannot read properties of undefined (reading '500')
    at VM1060 jsapi_compiled_gantt_module.js:4:176
(anonymous) @ VM1060 jsapi_compiled_gantt_module.js:4
jsapi_compiled_ui_module.js:315 Uncaught TypeError: this.qa.set is not a function
    at gvjs_.set (jsapi_compiled_ui_module.js:315:423)
    at gvjs_.set (jsapi_compiled_ui_module.js:343:179)
    at gvjs_.Pi (jsapi_compiled_ui_module.js:343:274)
    at jsapi_compiled_ui_module.js:345:269
gvjs_.set @ jsapi_compiled_ui_module.js:315
gvjs_.set @ jsapi_compiled_ui_module.js:343
gvjs_.Pi @ jsapi_compiled_ui_module.js:343
(anonymous) @ jsapi_compiled_ui_module.js:345
jsapi_compiled_gantt_module.js:4 Uncaught TypeError: Cannot read properties of undefined (reading '500')
    at jsapi_compiled_gantt_module.js:4:176
1 Answers

Too many errors and bloated constructs in your code to explain all.

Compare your code with this:

<gantt-chart></gantt-chart>

<script>
  customElements.define("gantt-chart", class extends HTMLElement {
    constructor() {
      super().attachShadow({mode:"open"})
             .append(this.gantt_container = document.createElement("div"));
    }

    connectedCallback() {
      console.log("<gantt-chart> connected");
      document.head.append(
        Object.assign(document.createElement("script"), {
          type: "text/javascript",
          src: "https://www.gstatic.com/charts/loader.js",
          onload: () => {
            console.log("charts loaded. Initializing gantt chart...");
            google.charts.load('current', {'packages': ['gantt']});
            google.charts.setOnLoadCallback(this.render);
          }
        })
      )
    }

    render = () => {
    // example from: https://developers.google.com/chart/interactive/docs/gallery/ganttchart
      function daysToMilliseconds(days) {
        return days * 24 * 60 * 60 * 1000;
      }

        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Task ID');
        data.addColumn('string', 'Task Name');
        data.addColumn('date', 'Start Date');
        data.addColumn('date', 'End Date');
        data.addColumn('number', 'Duration');
        data.addColumn('number', 'Percent Complete');
        data.addColumn('string', 'Dependencies');

        data.addRows([
          ['Research', 'Find sources',
            new Date(2015, 0, 1), new Date(2015, 0, 5), null, 100, null
          ],
          ['Write', 'Write paper',
            null, new Date(2015, 0, 9), daysToMilliseconds(3), 25, 'Research,Outline'
          ],
          ['Cite', 'Create bibliography',
            null, new Date(2015, 0, 7), daysToMilliseconds(1), 20, 'Research'
          ],
          ['Complete', 'Hand in paper',
            null, new Date(2015, 0, 10), daysToMilliseconds(1), 0, 'Cite,Write'
          ],
          ['Outline', 'Outline paper',
            null, new Date(2015, 0, 6), daysToMilliseconds(1), 100, 'Research'
          ]
        ]);

        var options = { height: 275 };

        var chart = new google.visualization.Gantt(this.gantt_container);

        chart.draw(data, options);
    }
  });
</script>

Related