-1

i am trying to understand the callback ngOnChanges() so i created the below posted example. but at the compile time despite the interface Post has values for its attributes title and content respectively, however, i do not receive any logs from ngOnChanges

please let me know how to use correctly

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->: changes[changedProperty].previousValue: " + changes[changedProperty].previousValue);
      console.log("ngOnChanges->: changes[changedProperty].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

as recommended i have added the ngOnChanges to observe changes in a prpoperty annotated with Input decorator as follows:

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

now, when I compile the code i add some values, i receive the following logs from ngOnChanges :

ngOnChanges->: changes[changedProperty].previousValue: undefined
post-list.component.ts:20 ngOnChanges->: changes[changedProperty].currentValue):

but the problem is when i keep adding more values, i do not receive any logs from the ngOnChanges please let me know why despite i keep adding more values that result in changing the contents of the object that is decorated with @Input??!

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->: changes[changedProperty].previousValue: " + changes[changedProperty].previousValue);
      console.log("ngOnChanges->: changes[changedProperty].currentValue):" + changes[changedProperty].currentValue);
    }
  }

}
Amrmsmb
  • 1
  • 27
  • 104
  • 226

3 Answers3

4

ngOnChanges() only gets called when component's inputs changed from the parent component(fields that marked with @Input decorator). But you have @Output fields. The idea of ngOnChanges() is to react to changes that were done by the parent.

Following your business logic, you can handle whatever you want straight in onSubmitPost.

Answer for the update 05.04.2021

You add values to the array itself. Since the link to the array hasn't changed, ngOnChanges() does not catch these changes. But if you put new link to the component and do the following in the parent:

component:

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

template:

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

Now value that you passed to the input changed and you will see the changes in the ngOnChanges(). The same goes for objects if you change object's property, angular won't see it as a change in ngOnChanges() since it only detects changes in @Input() values.

In order to catch those changes, you can use ngDoCheck hook. But it is power consuming, bear in mind not to perform heavy calculations there.

0

I think you are doing in correct way. Its just you missing to implement onChanges class. In latest Angular versions it straight throws error but in older version it does not.

Try this.

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);
    }
  }
}
Amit Gandole
  • 558
  • 8
  • 20
0

As already pointed out by @Vadzim Lisakovich

ngOnChanges() only gets called when component's inputs changed from the parent component

Now, the thing is that the input is compared using === operator i.e. shallow comparison. If you add something to the post array, the reference to the array stays the same thus no event is triggered.
To fix that you can implement ngDoCheck() or replace the reference.

Here is a very similar question to yours:
Angular2 change detection: ngOnChanges not firing for nested object
And of cause the documentation:
https://angular.io/guide/lifecycle-hooks#docheck