Ion item(s) with checkbox & katex is slow


Anyone has any idea why using “ion-item” in combination with “ion-checkbox” and “ng-katex-html” for rendering math formulas is slow when click on ion-checkbox (code below). The checkbox click action is slower when “ng-katex-html” contains html with katex math formulas and is even slower on mobile compared to web (difference reports like 1/3).

When no math formula inside “ng-katex-html”, ion-item’s behavior is just like in ionic demos. It is like additional classes added to elements inside ion-item are slowed down while being added by some thing.

Clicking many times (quickly) on ion-item, the item becomes gray and black due to slow rendering and recovers clicks stop.

Thus, difference is when formulas (already rendered) are clicked.

          <ion-item  *ngFor="let answer of answers; let i = index;">
            <ion-checkbox size="small" slot="start" [(ngModel)]="answer.isSelected"

            <div class="answer-content no-click" *ngIf="answer.text">
               <ng-katex-html [html]="answer.text | sanitizeHtml"></ng-katex-html> 

Help would be appreciated!
Thank you!

When attempting to improve performance of DOM rendering, it helps to understand how Angular change detection works. There are a bunch of blog articles that cover this, and I haven’t bothered to read enough of them in detail to recommend one over another.

The most crucial thing to understand is that any expression you provide that does get re-evaluated as part of change detection will potentially get evaluated an insane number of times, so it is super-important to make them as lightweight as possible.

  1. Best case scenario: a simple bound property:

Angular is smart enough to remember what foo was the last time it checked it, and if it hasn’t changed, the whole process goes very smoothly.

  1. Considerably worse, but some times unavoidable:

If you do have to do this, make getFoo() as light as you possibly can. If that’s impossible, look into alternative change detection strategies like OnPush. Generally, in situations like this, I choose to call getFoo() in the controller on my timing, and stash the result in a normal property, so the template can look like the first example.

So, specific things to avoid as much as you can:

  • function calls from a template
  • pipes
  • structural directives

Your sanitizeHtml pipe gets called just as if it were a function. I would try to get rid of it, or minimize how many times it is called by using alternate change detection.

I would also not use ngIf here, because every time that switch flips, everything has to get calculated again. Leave the element in the DOM, and simply control its visibility with CSS instead.