Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

How do I pass a value between child components that are populated using *ngFor ?.

I have tried using the @output decorator patterns and it results in erroneous behavior.

  1. How do to correctly use the @output. why does the expected results are not obtained. ?
  2. Is there any other way to achieve this functionality other than changing the data model?.

A JSON array is specified app.component.ts and it has a field salary. I would want to display a total field salary as we loop through the array and display it in the child component.

Here the goal is to print out the total salary dynamically as the elements get iterated. I try to achieve this using @output decorator by calculating the total salary of the child and then send it to the parent.

app.component.html

<div *ngFor="let person of persons">
<app-child [name]="person.name" [salary]= "person.salary" [totalsalary] = "totalsalary" 
(totalSalary)="setTotalSalary($event)">

 </app-child>
 <div>

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

app.component.ts

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  @Input() totalsalary:number=0;

persons = [{
  "name":"x",
  "salary":1
},{
  "name":"s",
  "salary":2
},
{
  "name":"y",
  "salary":2
}
]
setTotalSalary(totalSalary:number) {
 //   console.log("total  salary" +this.totalsalary)
  this.totalsalary = totalSalary;
}
}

child.component.ts

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

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

  @Input() name!:string;
  @Input() salary!:number;
  @Input() totalsalary!:number;
  @Output() totalSalary = new  EventEmitter<number>();

  constructor() { }

  ngOnInit(): void {
  }

  displayTotalSalary() {
    console.log("current salary"+this.salary)
    console.log("total  salary" +this.totalsalary)
let sum = Number(this.salary) + Number(this.totalsalary)
    this.totalSalary.emit(sum);
    return  Number(sum)
  }

}

child.component.html

<p>{{name}}</p>
<p>{{salary}}</p>
<p>{{displayTotalSalary()}}</p>

Expected Result :

x

1

1

s

2

3

y

2

5

Received :

x

1

6

s

2

8

y

2

10
question from:https://stackoverflow.com/questions/65642951/passing-values-between-child-components-in-ngfor

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
744 views
Welcome To Ask or Share your Answers For Others

1 Answer

displayTotalSalary() is being called two times for each child, first time for each child(taking the totalSalary to 1+2+2 =5) then again for each child that's why you are getting 5+1=6, 6+2=8 and 8+2=10.

This is because of the function call displayTotalSalary() in template, moving the call from template to the ts files fixes the issue.

ngOnInit(): void { this.salaryToDisplay = this.displayTotalSalary(); }

and in child template use<p>{{salaryToDisplay}}</p>

To know why function call in template is being called multiple times.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...