[IONIC 4] Error while displaying images loaded from device storage

A while ago I wrote a function that took a photo with the camera phone, saved it to the device’s storage and showed the photos that were already taken on a page. The function was almost entirely based on this great example and worked perfectly.

To display the images on the page I use this function inside a ng-container:
<ng-container *ngFor = "let img of images; index as pos">

Now I’m writing a new version of the app with some functionality identical to the old one, including the one I mentioned. But now when this function of displaying images on the page is triggered I get the following error:

TypeError: Cannot convert undefined or null to object

The maddening part is that the code involving this function is 100% the same as the previous one, which is working perfectly. Another thing, in the console I can see that the images were already loaded before the error was triggered.

My code:

const STORAGE_KEY = 'my_images';

export class MyPage implements OnInit {
	images = [];

	ngOnInit() {
		// When platform is ready, load stored images
		this.platform.ready().then(() => {
		  	this.loadStoredImages();
		});
	}

	loadStoredImages() {
		this.storage.get(STORAGE_KEY).then(images => {
			if (images) {
				let arr = JSON.parse(images);
				this.images = [];
				console.log(arr);

				// Populate local 'images' array with stored data
				for (let img of arr) {
					let filePath = this.file.dataDirectory + img.name;
					this.images.push({ name: img.name, filePath: filePath});
				}
				console.log(this.images);
			}
		});
	}
}

I would recommend you to console log each part of your method. What does the sotrage get returns? what does the arr value is after parsing the JSON, what’s the file path that you assemble? what is the result in images variable after onInit?

BTW, there’s one thing you should consider, maybe nothing to do with this, but with ionic, angular components that are meant for pages are ‘loaded’ onto the view and if you navigate they aren’t destroyed, instead they are still in the view but hidden which will allow you to make a quite fast tranistion when you go back to the previous page. Because of this reason is that is not recommended to put either load data methods or destroying listeners in the regular onInit and onDestroy methods, instead ionic recommends you to use their own lifecycle methods such as IonViewWillEnter (for fetching any data you will show) or IonViewWillLeave (to dispose any listener you may have around). More info about this on https://ionicframework.com/docs/angular/lifecycle

As you can see inside my loadStoredImages() function, I already doing this. All logs return what are expected, and all before the *ngFor function, which triggers the error. If you want you can see what exactly are the logs content in the link I posted, but since this is working in a parallel app I guess that there is not wrong with them.

I’m aware of that, that is why I have this line in the beginning of my function:

this.images = [];

Probably is not the best method to deal with it, but this “resets” the images array object every time I enter the page, which is what I want.

Can you get a stack trace to figure out exactly where this error is being triggered?

ERROR TypeError: Cannot convert undefined or null to object
    at Function.from (<anonymous>)
    at new CssUtilsDeprecations (fesm5.js:4976)
    at createClass (core.js:27865)
    at createDirectiveInstance (core.js:27685)
    at createViewNodes (core.js:38315)
    at createEmbeddedView (core.js:38174)
    at callWithDebugContext (core.js:39716)
    at Object.debugCreateEmbeddedView [as createEmbeddedView] (core.js:38986)
    at TemplateRef_.createEmbeddedView (core.js:27182)
    at ViewContainerRef_.createEmbeddedView (core.js:26963)

This is triggered in MyPage.html in the line of the *ngFor function:
<ng-container *ngFor="let img of images; index as pos" text-wrap>

I’m assuming that the at Function.from (<anonymous>) is the *ngFor loop. Before this error I receive the logs of the complete populated imagesarray.

No, I don’t think so. I think it’s line 9 of this file, borking on something in your template. I would look for elements in that template that are using any of those deprecated properties, because without one of them on there, that directive shouldn’t come into play. What happens if you take text-wrap off that ng-container?

Further commentary:

ng-container doesn’t actually turn into a DOM element, so only structural directives can be applied to it. The presence of text-wrap is pulling in the CssUtilsDeprecations directive, which is not structural and therefore assumes that it is sitting atop a DOM element. It isn’t, so blammo.

1 Like

Sorry for replying late, I had some major Windows issues.

Very nice to know! But can you tell me why this is working in another app then? I use this same code for some time and only now I faced this problem.

Probably because CssUtilsDeprecations didn’t exist until about a month ago.

1 Like

Makes sense. I will fix this in that app too then. Again, thank you very much for all your help!

@rapropos can you please explain what significance this (extensive!) list of deprecations has? Should we not be using these properties any more??

1 Like

Extrapolating from the comment that closes this issue, it seems that it’s an attempt to unify syntax amongst Angular/React/??? users, and the recommendation is to do all CSS stuff in style sheets, define classes in there, and then bind [class.whatever] in the template instead of trying to bind [css-thingy] directly in the template.

1 Like

Thanks a lot, that’s worth knowing.