At what point does Angular2 assess template values? What is the effect on overall performance when it encounters complex methods like `complexMethod()`?

We are currently working on an Angular2 application.
I recently developed a versatile component for handling a group of checkboxes.

Since the component is supposed to be generic and handle any set of objects belonging to the same TypeScript class, I decided to implement a model adapter approach inspired by Wicket. Though not exactly similar, as I am passing individual callbacks:

            <wu-checkboxes [groupName]="'includedApps'"
                           [options]="availableApps"
                           [valueCallback]="appsValueCallback"
                           [labelCallback]="appsLabelCallback"
                           [equalsCallback]="equalsCallback"
                           [(checkedOptions)]="applicationGroup.applications"
                           (checkedOptionsChange)="onCheckedOptionsChange()"
            >
            </wu-checkboxes>

The callback functions are defined as follows:

appsValueCallback = (app: RegisteredApplication) => ""+app.id;
appsLabelCallback = (app: RegisteredApplication) => app.title;
equalsCallback = (a1: RegisteredApplication, a2: RegisteredApplication) => a1.id === a2.id;

availableApps: RegisteredApplication[];
includedApps: RegisteredApplication[];

In the actual component, we have this code snippet:

<div *ngFor="let option of _options">
    <label>
        <input type="checkbox" [name]="groupName"
               [value]="valueCallback(option)"
               [checked]="shouldBeChecked(option)"
               (change)="handleCheckboxChange(option, $event)"
               />
        {{labelCallback(option)}}
    </label>
</div>

Also, there is this method:

shouldBeChecked(option: ItemType): boolean {
    console.log("shouldBeChecked() called.", option, this.checkedOptions);
    return ...
}

I anticipated that shouldBeChecked would only be executed once per checkbox.
However, after checking the console, shouldBeChecked() seems to be invoked multiple times, even if there's just one checkbox during the initial rendering. I confirmed that ngAfterViewChecked and ngAfterViewChanged are triggered only once for the checkboxes component.

TLDR:

  • Why is Angular2 calling shouldBeChecked so frequently?
  • Does this suggest a mistake in the setup of the component, page, or application?
  • How can I determine the root cause of these repeated calls? The stack traces don't offer much insight to me.

Answer №1

Consider this perspective - (and I am simplifying to focus on your specific question) Angular's change detection operates by monitoring asynchronous events (such as key presses, clicks, ajax requests, etc), and when an event occurs, Angular recognizes that a variable binding may have changed. Therefore, it scans through all bindings to verify if the value has indeed changed.

So, if you are binding to the result of a function call, the only way to determine if the binding has changed is to execute the function and assess the outcome. This process repeats during every change detection cycle (whenever an asynchronous event triggers).

(Although this explanation is simplified, it emphasizes the fact that Angular must invoke the function each time it needs to check for changes in the binding).

In addition, development mode exacerbates the situation by causing Angular to scrutinize each binding twice for error checking purposes. Consequently, this amplifies the frequency at which your function is called.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular - Error: Unable to access properties of an undefined object (reading 'showSpinner')

When attempting to run the following code block, I encountered the following error message: core.mjs:6485 ERROR Error: Uncaught (in promise): TypeError: Cannot read properties of undefined (reading 'showSpinner') async ShowData() { if(this. ...

The ngInit function is not functioning properly as a result of the build mode in use with the

When setting up a library with the specified configuration, installing it on the application side, and inheriting and using it, an interesting behavior is observed. If `ng build --prod=true` is executed, the `ngOnInit` function will not be called. However, ...

Ways to establish whether an Angular form has been attempted for submission or not

Is there a way to identify when a user tries to submit an Angular form in order to display information about any invalid fields only when submission is attempted? ...

Issue detected in React Rollup: the specific module 'name' is not being exported from the node_modules directory

Currently in the process of creating a library or package from my component. The tech stack includes React, Typescript, and various other dependencies. Encountering an error while using Rollup to build the package: [!] Error: 'DisplayHint' is ...

How can I limit props.children in a React TypeScript component?

import React from 'react'; import './App.css'; import Message from "./components/Message"; function App() { return ( <div className="App"> <Message> <p>Hello ...

How can I convert duplicate code into a function in JavaScript?

I have successfully bound values to a view in my code, but I am concerned about the duplicate nested forEach loops that are currently present. I anticipate that Sonarcube will flag this as redundant code. Can anyone advise me on how to refactor this to avo ...

Attempting to use a string as an index for the type `{ firstName: { inputWarning: string; inputRegex: RegExp; }` is not allowed

const checkRegexSignUp = { firstName: { inputWarning: "only letters", inputRegex: /^[a-z ,.'-]+$/i }, lastName: { inputWarning: "only letters", inputRegex: /^[a-z ,.'-]+$/i }, } const change = (e: ChangeEvent<HT ...

The error message "TypeError: router.back is not a function" indicates that

Testing out the back route navigation in next.js and encountering an error during the test: https://i.sstatic.net/O6Nax.png The function for going back: const router = useRouter(); const handleClick = useCallback(() => { if (router ...

Script execution is disabled on this system preventing the loading of content - ANGULAR V14

Every time I try to run my Angular project or any ng command, I keep encountering the following error message: ng : File C:\Users\achra\AppData\Roaming\npm\ng.ps1 cannot be loaded because running scripts is disabled on this ...

Move the cache folder for NextJS to a new location

Is it possible to customize the location of the cache folder currently located in "./.next/cache"? I am interested in modifying this because I am developing an application that receives high traffic daily, and I plan to deploy multiple applications from m ...

Using TypeORM with a timestamp type column set to default null can lead to an endless loop of migrations being

In my NestJs project using TypeORM, I have the following column definition in an entity: @CreateDateColumn({ nullable: true, type: 'timestamp', default: () => 'NULL', }) public succeededAt?: Date; A migration is gene ...

Guidelines for effectively managing and notifying users of unrecoverable exceptions during APP_INITIALIZER execution

During the initialization of my Angular5 app, it retrieves a configuration file from the backend using APP_INITIALIZER. If the app fails to load this configuration file, I want to display a message to the user indicating the issue. providers: [ AppConfig ...

Enabling withCredentials: true in Angular 2 for all http requests

Currently, I am working with Angular 2 (specifically version angular-cli: 1.0.0-beta.11-webpack.9-4) and I need to ensure that withCredentials is set to true for each http request. Initially, I managed to set it up for a single request like this: http.get ...

NestJS enforces HTTPS for Swagger redirects, whereas other endpoints are allowed to work on HTTP

I'm running into a strange problem with the Swagger interface on my NestJS server, which is hosted on a Windows Server environment and managed by PM2. While all other endpoints work fine over HTTP, the Swagger interface can only be accessed via HTTPS. ...

Can you explain the definition of const?

Can someone explain why it is necessary to include the keyword const in the following line of code while using angular2dart: directives: const [HeroDetailComponent] Thank you for clarifying this aspect of component properties. ...

Looking for guidance on integrating REST API consumption features into Ionic Framework 3.x?

It's been a long time since I last used the ionic framework. The version I worked with was 1, where every page created with Ionic Creator had its own controller for adding JavaScript code to consume my REST framework. Now that I've downloaded th ...

Angular fails to identify modifications in specific project files

https://i.stack.imgur.com/9XRnS.png After making changes to auth.gaurd.ts, create-order.service.ts, and order.model.ts, I'm facing an issue where the changes are not being reflected in my application. Interestingly, all other files seem to work fine. ...

I'm curious about what exactly happens when the NextJS Link component is triggered and how we can effectively capture and respond

As I was developing a simple navbar that uses a JSON data to dynamically generate its links, I encountered the need to visually persist the active link/route. To achieve this, I experimented with two different implementations: Initial approach: In the Me ...

What are the best indexes to implement on a high-volume table with millions of rows and various filtering criteria?

I currently have a massive table with millions of rows. Users are able to select various filters across multiple columns, such as: Year Month Product HSCode Chapter Country Port Unit Importer/exporter name Type I am considering making it a requirement to ...

Why do my subscriptions in Angular 9 load sequentially rather than simultaneously?

In my Angular 9 project, I am trying to load a series of objects containing image data. My goal is to first load all the objects and then fetch the image data for each object afterwards. In the `ngOnInit` function in my component.ts file, I have the follow ...