The ngOnChanges method fails to exhibit the anticipated modifications in a variable

Trying to grasp the concept of the ngOnChanges() callback, I created an example below. Despite having values for the attributes title and content in the Post interface during compile time, I do not see any logs from ngOnChanges.

Please advise on the correct usage.

app.component.ts:

import { Component, OnInit, OnChanges, SimpleChanges, Output, EventEmitter } from '@angular/core';

export interface Post {
  title: string;
  content: string;
}

@Component({
  selector: 'app-post-create',
  templateUrl: './post-create.component.html',
  styleUrls: ['./post-create.component.css']
})
export class PostCreateComponent implements OnInit {

  @Output() post: Post;
  @Output() onPostSubmittedEvtEmitter: EventEmitter<Post> = new EventEmitter<Post>();

  constructor() { 
    this.post = {} as Post;
  }

  ngOnInit(): void {}

  ngOnChanges(changes: SimpleChanges) {
    for (let changedProperty in changes) {
      console.log("ngOnChanges-> previousValue: " + changes[changedProperty].previousValue);
      console.log("ngOnChanges-> currentValue: " + changes[changedProperty].currentValue);
    }
  }

  onSubmitPost(post: Post) {
    this.post = {
      title: this.post.title,
      content: this.post.content
    };
    this.onPostSubmittedEvtEmitter.emit(this.post);
    console.log("onSubmitPost-> post.title: " + post.title);
    console.log("onSubmitPost-> post.content: " + post.content);
  }

}

update 05.04.2021

I have now added ngOnChanges to monitor changes in a property annotated with the Input decorator:

@Input() postsToAddToList: Post[] = [];

Upon compiling the code and adding values, I receive the following logs from ngOnChanges:

ngOnChanges-> previousValue: undefined
ngOnChanges-> currentValue:

However, the issue arises when adding more values as I do not see any logs from ngOnChanges despite changing the contents of the object decorated with @Input. Can anyone explain why?

post-list.component.ts:

import { Component, Input,OnInit, OnChanges, SimpleChanges, Output, EventEmitter } from '@angular/core';
import { Post } from '../post-create/post-create.component';

@Component({
  selector: 'app-post-list',
  templateUrl: './post-list.component.html',
  styleUrls: ['./post-list.component.css']
})
export class PostListComponent implements OnInit {

  constructor() {}

  @Input() postsToAddToList: Post[] = [];
  ngOnInit(): void {}

  
  ngOnChanges(changes: SimpleChanges) {
    for (let changedProperty in changes) {
      console.log("ngOnChanges-> previousValue: " + changes[changedProperty].previousValue);
      console.log("ngOnChanges-> currentValue: " + changes[changedProperty].currentValue);
    }
  }

}

Answer №1

ngOnChanges() is a lifecycle hook in Angular that only gets called when the component's inputs change from the parent component (fields that are marked with the @Input decorator). However, if you have @Output fields, ngOnChanges() will not react to those changes. Instead, consider handling any necessary logic directly in the onSubmitPost method.

As of the update on 05.04.2021, adding values to an array itself does not trigger ngOnChanges() since the link to the array has not changed. To address this, you can create a new reference to the array in the parent component:

this.yourArrInTheParent = [...this.yourArrInTheParent];

Then, in the template:

<app-post-lis [postsToAddToList]="yourArrInTheParent"></app-post-lis>

This way, the input value has changed and ngOnChanges() will detect these updates. Similarly, for object properties, Angular will not recognize them as changes in ngOnChanges(), as it only detects changes in @Input() values. If you need to monitor such changes, you can utilize the ngDoCheck hook, but be wary of heavy computations in this hook due to its performance implications.

Answer №2

It seems like you're on the right track, but you might be missing the implementation of the onChanges class. In newer versions of Angular, this would result in an error being thrown, whereas in older versions it may not.

You can try adding the following code:

export class PostListComponent implements OnInit, OnChanges{
    
  constructor() {}

  @Input() postsToAddToList: Post[] = [];
  ngOnInit(): void {}


  ngOnChanges(changes: SimpleChanges) {
    for (let changedProperty in changes) {
      console.log("ngOnChanges->: changes[changedProperty].previousValue: " + 
           changes[changedProperty].previousValue);
      console.log("ngOnChanges->: changes[changedProperty].currentValue):" + 
           changes[changedProperty].currentValue);
    }
  }
}

Answer №3

It has been brought to our attention by @Vadzim Lisakovich

ngOnChanges() is only triggered when the inputs of a component change from its parent component

What's interesting is that input comparison uses the === operator, which results in shallow comparison. This means that if you add something to the post array, the reference to the array remains the same and no event is fired.
To address this issue, you can utilize ngDoCheck() or update the reference.

If you're interested, here's a similar question:
Angular2 change detection: ngOnChanges not firing for nested object
And, of course, there's always the documentation for further information:
https://angular.io/guide/lifecycle-hooks#docheck

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

Utilize Javascript to refine JSON data strings

Currently, I am tackling a small project and facing a minor JS issue. The JSON string that I have looks like this: var jsObj = { "templates": { "form0": { "ID": "MyAlertNew", "isVisible": "true", ...

Tips on saving Firebase Storage image url in Firebase database?

How do I store the URL of an image uploaded to Firebase Storage in Firebase Database? When executing the code below, I encounter the following error: Uncaught (in promise) FirebaseError: Function DocumentReference.set() called with invalid data. Unsuppor ...

Sequelize Authentication is unable to finalize

As I delve into the world of node.js and sequelize, I am encountering a persistent error: /home/cbaket/test/test.js:9 .complete(function(err) { ^ TypeError: undefined is not a function at Object.<anonymous> (/home/cbaket/test/test.js:9: ...

Issue encountered in the express route when attempting to send an email to the user with nodemailer and reactjs

When attempting to send an email to the user who submitted the application using ReactJS and Nodemailer, an error stating "route not found" is encountered. Warning: Location "/contact?name=milan&email=xedikaka%40gmail.com&phone=9843698469&city ...

Encountered a technical issue while attempting to assign a value in Angular

In my Angular application, I have defined an object called Task: export class Task { taskId: number; description: string; date: string; project: Project; } Within a component, I am working on implementing a method that will add a new task. To ac ...

In my Vue watch method, I have two parameters specified, and one of them remains constant without any changes

Currently, I am attempting to access a method within my watch function with two parameters. Here is the code snippet for the method: onBoolianChange(value, willChange) { willChange = (value === false) ? true : false; }, watch: { "e ...

Encountering the error "Cannot access property 'stroke' of undefined" when utilizing constructors in React and p5

Hi there, I'm having trouble with my React code and could really use some assistance. Being new to React, I'm trying to create a collision system between multiple bubbles in an array, but I keep running into this undefined error: import React, ...

Troubleshooting Angular 2 routerLink functionality issues

I have gone through all the tutorials and still can't figure out what I am doing wrong. AppModule : import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } fr ...

What is the proper way to detach an event listener from a class?

I am facing a challenge when trying to remove an event listener. After running the script, I receive an error message stating that changeGirl.off("click") is not a function. Despite this issue, everything else within the code is working perfectly fine. Any ...

What is the best method for transferring properties to the parent component using Vue router?

I have a multi-step form that each step has a different header structure. The only variation in the header among the steps is the wording, which changes as you progress through the steps. I am looking for a way to achieve this using Vue Router: pa ...

Getting data from a PHP request using AngularJS can be achieved by creating an HTTP request in

I am trying to send a basic REST service request using Angular for the PHP code below. Unfortunately, the request is resulting in an error. Check out the live code here PHP Code <?php /* Simple array */ $json = array("status" => 0, "msg" => ...

Having trouble managing TypeScript in conjunction with React and Redux

As a newcomer to TypeScript, I find myself struggling to grasp the concepts and know where to start or stop. While there are abundant resources available online, I have not been able to effectively utilize them in my project. I am hopeful for some guidance ...

Angular Commandments: Understanding the Directives

Within my code, there is a specific directive view that I am utilizing: <div class="busy-indicator angular-animate" ng-show="busy"></div> <div class="breadcrumblist" ng-class="atTopLevel ? ['at-top-level'] : null"> <div ...

What is causing the unexpected impact of the "Product Quick View" JavaScript plugin on divs that are not being activated by user interaction?

As a newcomer to web design, I have implemented the "Product-Quick-View" plugin from CodyHouse on my website. Upon clicking the DEMO button and inspecting the code, you will find the following: <body> <header> <h1>Product Q ...

What's the best method for uploading a file to AWS S3: POST or PUT requests?

Could you please provide insights on the advantages and disadvantages of utilizing POST versus PUT requests for uploading a file to Amazon Web Services S3? Although I have come across some relevant discussions on platforms like StackOverflow, such as this ...

Troubleshooting: How to resolve the issue of "Error [ERR_HTTP_HEADERS_SENT]: Unable to set headers after they have been sent to the client"

* **> const PORT=8000 const express = require('express') const {v4:uuidv4}=require('uuid') const bcrypt =require('bcrypt') const jwt =require('jsonwebtoken') const cors=require('cors') const {MongoClie ...

text box with an immobile header

As the browser window size decreases, the layout changes. However, when scrolling down, the search text box moves up and is no longer visible due to its lack of fixation. How can I make the search text box stay fixed as I scroll down? I tried implementing ...

There was an issue with the layout detection in Angular. The app-layout selector could not find a matching element in the code

Currently diving into the world of Angular and embarking on my first project, I've hit a roadblock. After initiating a terminal with the server, all I get is a blank page when I load my browser. Upon inspecting the page using f12, an error message pop ...

Design: Seeking a layout feature where one cell in a row can be larger than the other cells

To better illustrate my goal, refer to this image: Desired Output <\b> Currently, I'm achieving this: current output Imagine 7 rows of data with two columns each. The issue arises in row 1, column 2 where the control needs to span 5 row ...

What is the process for importing a JSON5 file in Typescript, just like you would with a regular JSON file?

I am looking to import a JSON5 file into a JavaScript object similar to how one can import a JSON file using [import config from '../config.json']. When hovering over, this message is displayed but it's clearly visible. Cannot find module & ...