TypeError: Cannot set property 'checked' of null

I want to dynamically activate some checkboxes when the user enters the page. For this I am saving the IDs of the HTML checkbox elements in a service. When the user enters the page, this service is accessed and returns an array with these IDs. The active elements are checked in each loop.

this.platform.ready().then(() => {
	let checboxState = this.service.checboxState;
	if (checboxState !== undefined && checboxState.length > 0) {
		checboxState.forEach(checbox => {
			let element = document.getElementById(checbox.id) as HTMLInputElement;
			element.checked = true;
		});
	}
});

But I’m getting this error:

Uncaught (in promise): TypeError: Cannot set property ‘checked’ of null

Which can be a indicator that Javascript function is firing before DOM is loaded. If that is the case, why platform.ready() isn’t working? I tried also with:

  • document.addEventListener("DOMContentLoaded",() => {}
  • window.onload = () => {}

but no success.


I managed to make the function work by adding a setTimeout() before the function, so how do I correctly wait the HTML elements to load before firing the JS function?

Remove the logic in platform and place inside ngOnInit method instead.
https://angular.io/guide/lifecycle-hooks

platform.ready() is already inside ngOnInit().

I do virtually everything in my power to avoid any direct DOM interaction, because I consider it the domain of frameworks, not app-level code. Therefore I would strongly urge you to redesign this so that you never need to type “document” at all.

What I would do instead is to have a backing array in my page controller (which could be centrally coordinated in a service, if it needs to be reused in many pages). It could be an array of FormControls, or some other structure that maintains a boolean value indicating the checked state of each checkbox. I would then bind either [ngModel] or [checked] to that property, using an ngFor loop in the template to avoid excess template boilerplate.

1 Like