I am new to Ionic and angular. I notice some peculiar issues.
Whenever I need to access the DOM i have to do a time out query to get dynamic elements.
event if I use ngAfterViewInit - this doesn’t work.
So for example when trying to access a dynamically generated url this wont work.
ngAfterViewInit() {
var that = this;
that.img = that.el.nativeElement.querySelector('img');
alert(that.src);
}
Hover this will
ngOnInit() {
var that = this;
setTimeout(function () { // still buggy need to wait for dom to load.
that.img = that.el.nativeElement.querySelector('img');
alert('cache ' + that.src);
ImgCache.useCachedFile(that.img, function (){
}, 300);
}
That’s not a good idea. It’s “unprincipled” to reach directly into the DOM in the Angular framework anyway. If you’re talking about doing it from within a component, it could cause performance issues. Every time you change the DOM, Angular needs to run a lot of checks, and you could get flicker or slowdown that is hard to debug because the issue is coming from one of many components on the page.
Instead, let Angular change the DOM by interacting through Angular directives (ngIF etc) and other tools. If you want to modify an image, bind the image source to a variable or an Observable, so the image is loaded automatically when it is ready.
This is my code - the url isnt registered unless I put the timeout on. I have noticed this in other areas and I want to do it without the time out. I am using Ios emulator by the way
import { Component, ElementRef, Input, OnInit, AfterContentInit } from '@angular/core';
import ImgCache from 'imgcache.js';
/**
* This component will be in charge of caching images and use them when the app is offline
*/
@Component({
selector: 'lazy-img',
template: `
<div [ngClass]="{ 'placeholder': hidden }">
<img [ngClass]="{ 'active': !hidden }" [src]="src" (load)="load()" (error)="error()" />
</div>
`
})
export class LazyImgComponent implements AfterContentInit {
@Input() src: string;
public img: HTMLImageElement;
public hidden: boolean;
constructor(public el: ElementRef) {
this.hidden = true;
};
ngAfterContentInit() {
var that = this;
that.img = that.el.nativeElement.querySelector('img');
that.img.crossOrigin = 'Anonymous';
// check if the images are already cached
ImgCache.isCached(that.src, (path: string, success: boolean) => {
if (success) {
alert('cache ' + that.src);
ImgCache.useCachedFile(that.img, function (){
alert('now using local copy');
}, function(){
alert('could not load from cache'); // desnt work with live reload
})
} else {
alert('no cache ' + that.src)
ImgCache.useOnlineFile(that.img);
ImgCache.cacheFile(that.src, () => { });
}
});
}
/**
* This function will show the image when it has loaded
*/
load(): void {
this.hidden = false;
}
/**
* This function will be triggered when http request fails
*/
error(): void {
this.img.remove();
}
}
Don’t use your input as src. Set src to be some placeholder if your input is falsy, and set it to the input value once the input comes through to the component. (So you could define src as a getter for example.) That is shorter, does not break, and removes the call to nativeElement.
If it were my code though, I would refactor to an Observable, and set the image source to be [src]="obs | async" where obs is an Observable that emits values from either database or cache.
Just because something works doesn’t mean you should do it. The second code works because it takes time for the image to arrive at the component. But maybe it takes less than 300ms today, and tomorrow maybe it takes more. You want your code to work on a variety of devices, right? You have no way to control how many processes are already running on those devices. It’s best to write code that will always work, not just work for you on your system right now.
I agree. I am trying to work out how as well using this framework - hence asking. I thought ionViewDidLoad() {} was similar to document ready in jquery. I never had these issues in jquery.
jQuery is a Javascript library. Angular is a Javascript framework. Not the same thing. Angular builds an entire structure around the DOM. But I’m concerned that I said not to use nativeElement and you did it again anyway. It makes me feel that I am talking to myself. Look. This is what you need.
Basic understanding of Javascript ES2016.
Basic TypeScript
Basic Angular
What is a Promise, what is an Observable (optional but a very good idea)
and after that
Start programming in Ionic.
I think you should spend a couple weeks on (1)-(4). Then questions like the one you are asking will be a lot easier to answer.