Reputation: 165
When my template renders the function inside ngOnChanges fires one time, and then only when an @input changes. Is this the expected behaviour and how can I prevent it?
Child:
export class MobileMenuComponent implements OnInit, OnChanges {
@Input('test') dezeTest: string;
//declare menu
menu;
constructor() {
//define menu
this.menu = {state: 'inactive'};
}
togglemenu() {
var that = this;
if (that.menu.state === 'inactive'){
that.menu.state = 'active';
}
else {
that.menu.state = 'inactive';
}
}
ngOnChanges(changes: SimpleChanges) {
this.togglemenu();
}
}
Upvotes: 2
Views: 12125
Reputation: 1060
To expand on existing answers, and address a typing question raised in a comment at the same time:
The SimpleChange#firstChange field exists for this exact case.
Alternatively, because the value is set on your Component before ngOnChanges is called, you can also check if a field has changed, followed by if it's set:
ngOnChanges(changes: { myField: SimpleChange }) {
if(changes.myField && this.myField){
// do a thing only when 'myField' changes and is not nullish.
}
// Or, if you prefer:
if(changes.myField && changes.myField.firstChange){
// Do a thing only on the first change of 'myField'.
// WARNING! If you initialize the value within this class
// (e.g. in the constructor) you can get null values for your first change
}
}
Another little warning: If you were to use tools like WebStorm to rename 'myField' on your Component, the 'myField' of the ngOnChanges method parameters ({myField: SimpleChange }) will NOT be updated. Which can lead to some fun Component initialization errors.
Upvotes: 3
Reputation: 563
As Dylan Meeus suggested, its the normal behaviour. but i would suggest a different solution, which takes advantage of the passed SimpleChange object. it contains a previousValue and a currentValue.. initially, the previousValue is not set. https://angular.io/docs/ts/latest/api/core/index/SimpleChange-class.html
ngOnChanges(changes : any){
if(changes.menu.previousValue){
this.togglemenu();
}
}
additionally, take care about OnChanges, since it fires on every input param... (you might add some more in the future)
Upvotes: 1
Reputation: 5802
This is the normal behaviour of ngOnChanges.
The ngOnChanges method will fire the first time because your properties have been checked, and subsequently fire when a property is updated. From the documentation, you can see
ngOnChanges is called right after the data-bound properties have been checked and before view and content children are checked if at least one of them has changed.
If you want to change it, you need to consider how you want to change it. That is not very clear from your question, but if you want to prevent the ngOnChanges from firing again, when a property is updated (I think that you want this because of your toggleMenu()
you might consider using the ngOnInit()
instead of ngOnChanges()
. Alternatively, you can block the togglemenu(); after the first time.
firstrun : boolean = true; // class variable
ngOnChanges(changes : SimpleChanges){
if(firstrun){
this.togglemenu();
firstrun = false;
}
}
Alternatively, as hinted at earlier, another lifecycle hook might suit your needs better.
Upvotes: 6