0

I have a problem with Anglular 8 and binding input parameters from parent component to child component. I have the following setup:

-app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'parent-child-binding';
  showTitle: boolean = true;
  childData = [];

  onBoolean(){
    this.showTitle = !this.showTitle;
  }

  onComplexAdd(){
    this.childData.push("data 4");
    this.childData.push("data 5");
  }

  onComplexEdit(){
    this.childData[0] = "data 1 edited";
    this.childData[1] = "data 2 edited";
  }
  onComplexNew(){
    this.childData = [
      "data 1",
      "data 2",
      "data 3"
    ]
  }
}

-app.component.html

<button (click)="onBoolean()">Boolean Bind</button>
<button (click)="onComplexNew()">Complex Object New</button>
<button (click)="onComplexEdit">Complex Object Edit</button>
<button (click)="onComplexAdd">Complex Object Add</button>
<app-child [data] = "childData" [showTitle]="showTitle"></app-child>

-child.component.ts

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

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit, OnChanges {
  
  @Input() showTitle : boolean = true;
  @Input() data : Array<any>;
  
  constructor() { }


  ngOnChanges(changes: SimpleChanges): void {
    console.log(changes);
  }

  ngOnInit(): void {
  }

}

-child.component.html

<h3 *ngIf="showTitle">Hello from child</h3>
<p *ngFor="let item of data">{{item}}</p>

So when I start I see the following:

screen1

and the console:

console1

When I click on the first button, as expected the title Hello from child shows and disappears. When I click on the second button, as expected I see:

screen2

and the console:

console2

When I click on the third and forth buttons, nothing happens, not in the UI or console (the onChanges method seems that is not firing).

An I doing something wrong, or this that I want to achieve is not possible?

Best regards, Julian

EDIT: After a comment and an answer from @MBB and @Apoorva Chikara, I've edited the code.

<button (click)="onBoolean()">Boolean Bind</button>
<button (click)="onComplexNew()">Complex Object New</button>
<button (click)="onComplexEdit()">Complex Object Edit</button>
<button (click)="onComplexAdd()">Complex Object Add</button>
<app-child [data] = "childData" [showTitle]="showTitle"></app-child>

The edition made the buttons to act (do something), but it is not what I expect. What I mean: When I click on the Complex Object Edit button in the UI I see:

screen3

But in the console, there is no ngOnChanges callback firing, but the binded object has changed, as we can see on the print screen (<p *ngFor="let item of data">{{item}}</p>) fired and printed out the new values.

The same happens when I click on the Complex Object Add button. In the UI I see:

screen4

But in the console the ngOnChanges callback is not firing, but the UI is containing the new added data.

I'm confused, can anyone advice please?

Julian
  • 375
  • 1
  • 8
  • 23
  • 1
    Why cant you change the lines (onComplexEdit) -> onComplexEdit() (onComplexAdd) -> onComplexAdd() – MBB May 10 '21 at 13:48
  • Hi @MBB thanks for your comment! I've edited the original question, because the change that you are suggesting is valid and proper, but not solve my problem. – Julian May 11 '21 at 05:43

1 Answers1

2

You have a very simple fix, you are not calling a function instead assigning its definition :

<button (click)="onComplexEdit()">Complex Object Edit</button> // call it as a function
<button (click)="onComplexAdd()">Complex Object Add</button>// call it as a function

The issue, you are facing for NgonChanges is due to the arrays passed by reference, this has a good explanation why this happens.

Apoorva Chikara
  • 8,277
  • 3
  • 20
  • 35
  • Hi @Apoorva Chikara thanks for your answer! I've edited the original question, because the change that you are suggesting is valid and proper, but not solve my problem. – Julian May 11 '21 at 05:44
  • What does it show in the Ngchanges? Can you add the details in the question now? – Apoorva Chikara May 11 '21 at 05:49
  • This is the problem. In the callback `ngOnChanges` I have a `console.log(changes)`, but in the last two buttons, there is nothing in the console window. – Julian May 11 '21 at 05:52
  • It seems you are getting value of type: `SimpleChanges` what is it? Try removing that and see what you get. – Apoorva Chikara May 11 '21 at 05:59
  • No, I'm not getting any value, because it seems that the callback function `ngOnChanges` never fires. If it fires there will be something in the `changes` argument, and it will be logged in the console window – Julian May 11 '21 at 06:04
  • If you see the updated values on the view that means the correct values are being passed. However, the values can't be seen in the console as they are passed by reference. To get into more details you should check [this](https://stackoverflow.com/questions/47696848/angular-ngonchanges-not-updating-value). – Apoorva Chikara May 11 '21 at 06:10
  • Yes thanks! The second answer, answered my question. So it is not possible to achieve this behavior with the setup I have. – Julian May 11 '21 at 06:22
  • I'll mark this answer, but please, can you edit the answer, so the link to the other question is visible there. Thanks again! – Julian May 11 '21 at 06:23
  • 1
    Sure, you can accept the answer. Meanwhile I will update the answer. – Apoorva Chikara May 11 '21 at 06:28