Reputation: 53
I am trying to learn Angular 2 and am trying to figure out the best way to implement some functionality with change detection. Basically I have a structure of components like this:
<parent-component>
<child-component [input]="getData(1) | async"></child-component>
<child-component [input]="getData(2) | async"></child-component>
</parent-component>
What I want to do is to detect when the inputs for the child components get updated in the same digest cycle, and then call some function in the parent component class. In this way I can use the parent component to process multiple changes at once, rather than process each change one-at-a-time. Is it possible to do this?
Upvotes: 0
Views: 3760
Reputation: 115
Build an AND function in your parent component. This assumes you have @Outputs on your child components firing off events when the inputs are submitted.
<parent-component>
<child-component (submitted)="increaseState()" [input]="getData(1) | async"></child-component>
<child-component (submitted)="increaseState()" [input]="getData(2) | async"></child-component>
</parent-component>
Parents .ts
state = 0;
increaseState(){
this.state++
}
function() {
if(state === 2) {
*process values*
}
}
Upvotes: 0
Reputation: 29335
combine them with zip or combineLatest
in the component:
//now filtering out falsey values for getData
// make it .filter(v => v !== undefined) to ignore undefined specifically
dataOne$ = getData(1).filter(v => v);
dataTwo$ = getData(2).filter(v => v);
combined$ = Observable.zip(dataOne$, dataTwo$).do(e => console.log('do whatever you want here');
Or:
combined$ = Observable.combineLatest(dataOne$, dataTwo$).do(e => console.log('do whatever you want here');
in template:
<parent-component *ngIf="combined$ | async as combined">
<child-component [input]="combined[0]"></child-component>
<child-component [input]="combined[1]"></child-component>
</parent-component>
Or possibly:
<parent-component >
<child-component *ngFor="let input of combined$ | async" [input]="input"></child-component>
</parent-component>
The first will make the parent and children instantiate only when combined resolves at least once.
the second will have the parent instantiate immediately, but the children won't instantiate until both items have resolved once.
There is a subtle benefit to the first option, in that the parent component's change detection will trigger everytime the observable it is subscribed to in async updates if you are using onpush change detection, it will not in the second case, though the do operator will always fire no matter what.
zip will fire when only both observables update, and give you the value in pairs
combineLatest will fire everytime one of them fires (AFTER both have fired once) and give you the latest value from the other.
Upvotes: 1
Reputation: 914
in your .ts file set vars
var data1;
var data2;
constructor()
{
getData1().then((d)=>{data1=d})
getData2().then((d)=>{data2=d})
}
in your html do
<parent-component>
<child-component *ngIf="data1 && dat2" [input]="getData(1) | async"></child-component>
<child-component *ngIf="data1 && dat2" [input]="getData(2) | async"></child-component>
</parent-component>
Upvotes: 0
Reputation: 105517
You can use ngAfterViewChecked
lifecycle hook. All hooks are part of change detection as explained in the Everything you need to know about change detection in Angular. The bindings update of the child components is performed as the first operation when Angular runs change detection for the current component. ngAfterViewChecked
is the hook that is triggered when the change detection for the current view component is finished.
Upvotes: 0