I use aurelia framework and Firefox browser. I became this error message when the page loads the first time: ‘TypeError: document.getElementById(…) is null’
Here the typescript code-snipped:
import { EventAggregator } from 'aurelia-event-aggregator';
import { HistoricalViewAll } from "./hist-view-all";
import { DeviceData } from "./model/device-data";
import { DeviceLocDataDTO } from "./dto/device-loc-data-dto";
import { activationStrategy } from 'aurelia-router';
import { autoinject } from 'aurelia-framework';
import { View } from "aurelia-framework";
@autoinject( EventAggregator )
@autoinject( HistoricalViewAll )
@autoinject( DeviceData )
@autoinject( DeviceLocDataDTO )
export class HistoricalViewSingle {
// any declarations...
constructor(private histDeviceDataDto: HistoricalViewAll, private deviceData: DeviceData, private deviceDataDTO: DeviceLocDataDTO, private ea: EventAggregator) {
console.log( "HistoricalViewSingle constructor called..." );
this.location = "Zurich";
this.deviceSelection = "allDevices";
}
determineActivationStrategy() {
console.log( "determineActivationStrategy() called..." );
return activationStrategy.replace;
}
activate( params, routeConfig, navigationInstruction ) {
this.params = params;
console.log( "params: " );
console.log( params );
this.routeConfig = routeConfig;
console.log( "routeConfig in HistoricalViewSingle: " );
console.log( this.routeConfig );
this.routeConfig.navModel.setTitle = this.params.device;
console.log( this.params.device.substr( 3, 2 ) );
this.deviceInURL = params.device;
console.log( this.deviceInURL );
//necessary to get first the data before UI will be renderet...
return this.deviceDataDTO.postReqDeviceDataFromLocation( "devices-in-location", this.location, this.deviceSelection );
}
attached() {
console.log( "HistoricalViewSingle is attached..." );
this.deviceLocationList = this.deviceDataDTO.getDeviceLocationList();
this.deviceLocationHint = "Übersicht Filiale " + this.locationName;
if ( this.deviceLocationList.length != 0 ) {
this.noDeviceHint = "devDataOk"
this.setDeviceSelection( this.deviceInURL );
} else {
this.noDeviceHint = "Keine Sensordaten"
}
this.changeTimeWindow( 1 );
}
created(owningView, myView) {
console.log("created() call in HistoricalViewSingle");
console.log(myView);
//this.changeTimeWindow( 1 );
}
changeTimeWindow( hours: number ) {
var deviceId: string = this.selectedDevLocList[0].device_id;
console.log("DeviceKey in changeTimeWindow(): " + deviceId);
console.log(document.getElementById( 'chart-' + deviceId) + ' - chart-' + deviceId);
const ctx1: CanvasRenderingContext2D = ( document.getElementById( 'chart-' + deviceId ) as any ).getContext( '2d' );
this.histDeviceDataDto.changeTimeWindowForOneDevice( hours, deviceId, ctx1 );
}
}
The error will caused in this line:
const ctx1: CanvasRenderingContext2D = ( document.getElementById( 'chart-' + deviceId ) as any ).getContext( '2d' );
after first page-load I click on button ‘8h’ as example, I don’t receive the error and the data in chartjs diagram will be rendered ok. The canvas id could be something like this ‘chart-am-ZH-Office’ and it would be already correct in the first page-load. I tried also to call method changeTimeWindow() in lifecycle method created(), but with the same error.
Thanks for fast answer, but that doesn’t work also. The “theCanvas” in viewmodel is not defined…
The aurelia-documentation explain about refs not so many…
Any other tips please?
My apologies. I forgot the this. I’ve updated the original reply. I haven’t dwelt much with canvas so I’m not sure about the getContext() method. If that doesn’t work, make sure to debug the this.theCanvas and view that DOM object in your console debugger.
The problem is that a ref it doesn’t work in a repeat.for loop. if I remove the repeat.for then it works fine, that is, it chart is rendered. I suspect that I have a bug with the life-cycle of the components. I first get data in the activated method and in the method attachment I call the method that gets the canvas reference to render the chart.
The error message is the following:
“TypeError: _this.theCanvas is undefined”
ref would not work behind repeat.for or if.bind. You can refactor the stuff under repeat.for loop into a child component with its own js and html template. Then in the child component, you can get a valid ref.
I have found the solution myself after 4 days. The solution was to move this.devices = this.deviceDataDTO.getDeviceLocationList(); in the lifecycle method created(), so when the attached method would be called the data in devices are ready. the ref works also in use with repeat.for…
This error TypeError: document.getelementbyid(…) is null would seem to indicate that there is no such element with an ID passed to getElementById() exist. This can happen if the JavaScript code is executed before the page is fully loaded, so its not able to find the element. The solution is that you need to put your JavaScript code after the closure of the HTML element or more generally before < /body > tag.