I'm trying to create a canvas in my custom lightning component. This is a child component of another component. The canvas draws few charts, and the methods are called only after both the script(Charts.js) is loaded and DOM is created. To achieve this I've done the following:

afterRender: function(component, helper){
    console.log("MS After rendere");
    let scriptLoaded    = component.get("v.scriptLoaded1");
    let domLoaded       = component.get("v.domLoaded1");
        helper.drawChartHelper(component, event, helper);


The js and helper and markup are as followed: Markup:

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" controller="SIAMFilterReportController" >   

<ltng:require scripts="{!$Resource.Chart}" afterScriptsLoaded="{!c.drawChart}"/>

<aura:attribute name="MITotSegmentVolMap" type="Map" />
<aura:attribute name="MITotSubSegmentVolMap" type="Map" />
<aura:attribute name="MITotSubSubSegmentVolMap" type="Map" />

<aura:attribute name="domLoaded1" type="Boolean" default="false" />
<aura:attribute name="scriptLoaded1" type="Boolean" default="false" />

<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

<div id="MSDiv1" class="slds-grid slds-wrap slds-gutters" aura:id="MSDivs">

    <div class="slds-size_1-of-1 charDiv" id="MSSubSegmentChartDiv" aura:id="MSSubSegmentChartDiv">
        <span class="slds-size_1-of-1 chartHeadings">
        <canvas id="MSSubSegmentChart" width="950" height="250" aura:id="MSSubSegmentCharts" class="chartStyle"></canvas>
    <div class="slds-size_1-of-1 charDiv" id="MSSubSubSegmentChartDiv">
        <span class="slds-size_1-of-1 chartHeadings">
        <canvas id="MSSubSubSegmentChart" width="950" height="250" aura:id="MSSubSubSegmentCharts" class="chartStyle"></canvas>


doInit : function(component, event, helper) {
    console.log("MS doInint");
drawChart   : function(component, event, helper){
    let scriptLoaded    = component.get("v.scriptLoaded1");
    let domLoaded       = component.get("v.domLoaded1");
        helper.drawChartHelper(component, event, helper);


drawChartHelper     : function(component,event,helper){

    let MITotSegmentVolMap          = component.get("v.MITotSegmentVolMap");
    let MITotSubSegmentVolMap       = component.get("v.MITotSubSegmentVolMap");
    let MITotSubSubSegmentVolMap    = component.get("v.MITotSubSubSegmentVolMap");

    let lineDataSet1  = this.lineHelper(component,event,helper,MITotSubSegmentVolMap,MITotSegmentVolMap);
    let lineDataSet2  = this.lineHelper(component,event,helper,MITotSubSubSegmentVolMap,MITotSubSegmentVolMap);

    console.log(">>>>> ",document.getElementById("MSSubSubSegmentChart"));
    console.log("@@@@---------**** ",component.getConcreteComponent().getElements());

    let ctx1 = document.getElementById("MSSubSegmentChart").getContext('2d');
    let myLineChart1 = new Chart(ctx1, {
        type    : 'line',
        data    : lineDataSet1
    let ctx2 = document.getElementById("MSSubSubSegmentChart").getContext('2d');
    let myLineChart2 = new Chart(ctx2, {
        type    : 'line',
        data    : lineDataSet2
lineHelper      : function(component,event,helper,mapToIterate,totalVolMap){

    let labelSet          = component.get("v.labelX");
    let dataSet           = [];
    let lineColor         = ['red','blue'];
    let lineDataSet;
    let colorIndex        = -1;
    for(let [key,value] of mapToIterate){
        let tempData = [];
        console.log('$$$ segmentDataMap key '+key);
        let totVol = parseInt(totalVolMap.get(key));

        let data ={
                label               : key,
                data                : tempData,
                lineTension         : 0,
                fill                : true,
                borderColor         : lineColor[++colorIndex],
                backgroundColor     : 'transparent',
                pointBorderColor    : 'green',
                pointBackgroundColor: 'lightgreen',
                pointRadius         : 5,
                pointHoverRadius    : 15,
                pointHitRadius      : 30,
                pointBorderWidth    : 2,
                pointStyle          : 'circle',
                scaleLineColor      : "black"

        lineDataSet = {
                labels   : labelSet,
                datasets : dataSet
    return lineDataSet;

In console.log(">>>>> ",document.getElementById("MSSubSubSegmentChart")); I get the following output:

Proxy {}
[[Handler]]: Object
[[Target]]: t.constructor
[[IsRevoked]]: false

Also at the bottom the page first I see the following error:

This page has an error. You might just need to refresh it. afterRender threw an error in 'c:MarketShareSegment' [Cannot read property 'length' of undefined] Failing descriptor: {c:MarketShareSegment}

After few seconds the same error message changes into:

Uncaught TypeError: Cannot read property 'initialize' of undefined throws at https://"myCustomDomain name is here"/Chart:13:18464

I think this is due to dom is not ready, but as per the code it should call the helper method only when both the DOM and script is ready.

PS: I'm using this in lightning out, and same code I used in another component and it is working perfectly fine.

  • So you meant to say that the one where it is working fine is not in the context of Lighening out? – user533 May 27 '19 at 0:41
  • using component.find('MSSubSubSegmentChart') may work. Have you tried it....we also have render event that works better than afterRender...can you try that as well...I am really not sure if this is something to with lighening out. Because lighening out, though it runs in LEX but it runs in the context of classic.. – user533 May 27 '19 at 0:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.