Reputation: 203
I have two components that communicate with each other, a regular component (parent) and a bootstrap modal component (child). Both the parent and the child have a table with records. In the parent's table each record has a checkbox. When I select one checkbox or more and click on a button, an event is triggered that tries to populate the child's table.
The child's table gets populated and I have the ability to delete the records I wish from it. If I delete some records, close the modal (close the child) and decide to send the same data from the parent to the child again, the Input
event is not triggered. However, if I choose to check different records in the parent and pass them to the child, the Input
event is triggered correctly.
Here's what I have:
ParentComponent.component.html
<child-component #createNewProductRequestModal [data]="newProductRequest"></m-child-component>
ParentComponent.component.ts
private onNewProductRequest(toSend){
this.newProductRequest = toSend;
$('#createNewProductRequestModal').appendTo("body").modal('toggle');
}
ChildComponent.component.ts
@Input('data')
set data(data: any) {
if (data !== undefined || data !== "") {
this.products = data;
console.log("data");
}
}
constructor() { }
ngOnInit() { }
To test if the data is changed before I render the child's table, I log the data passed by the parent to the console. With this code, every time I execute the parent's onNewProductRequest(toSend)
without changing the toSend
variable, the child's modal renders but doesn't execute the Input
event therefore not changing the data.
Upvotes: 3
Views: 2601
Reputation: 247
You can use ngOnChanges
Definition from angular docs
A callback method that is invoked immediately after the default change detector has checked data-bound properties if at least one has changed, and before the view and content children are checked.
You have some Input on child element
@Input() nameOfInput: any;
Your child component must implement OnChanges
like this:
export class ChildComponent implements OnChanges {
And in next step you want do something on every change of inputs.
ngOnChanges(changes: SimpleChanges) {
console.log(changes);
if ('nameOfInput' in changes) {
console.log('Old value: ', changes.nameOfInput.previousValue);
console.log('New value: ', changes.nameOfInput.currentValue);
}
}
Look at this example.
Upvotes: 2
Reputation: 1759
When you send the same data to the child component a second time, Angular does not register this as a change to the @Input(), as you are passing the same Object reference that you passed the first time, and Angular is just comparing the references.
Try this small change:
private onNewProductRequest(toSend){
this.newProductRequest = { ...toSend };
$('#createNewProductRequestModal').appendTo("body").modal('toggle');
}
This will mean that you pass a shallow copy of the data Object to the child, rather than just a modified version of the original Object. As this shallow copy will have a different reference to the original Object, Angular will pick it up as a change and trigger your @Input setter.
Upvotes: 1
Reputation: 158
When you assign the data to the input, the first time detect the changes because the object changes, but then if yo change properties inside the object the reference and the object still be the same, so the changes doesn't fire. The solution is clone the object that you're sending via input to the child. Try changing this line:
this.newProductRequest = toSend;
For this:
this.newProductRequest = {...toSend};
Upvotes: 2
Reputation: 1022
try
in child component
import {Component, OnChanges, SimpleChanges, Input} from '@angular/core';
ngOnChanges(changes: SimpleChanges) {
for (let propName in changes) {
let change = changes[propName];
let curVal = JSON.stringify(change.currentValue);
let prevVal = JSON.stringify(change.previousValue);
console.log(curVal);
console.log(prevVal);
}
}
Upvotes: 0