Angular.js: Detecting UNINITIALIZED_VALUE in $onChanges lifecycle hook

Created on 15 Jul 2016  ·  5Comments  ·  Source: angular/angular.js

With a scope watcher, you can detect if it is the first time the watcher is running by checking if the new and old values are the same:

$scope.$watch('expr', function (newValue, oldValue) {
    if (newValue === oldValue) {
        // first time running
    }
});

However, with the Angular 1.5 $onChanges lifecycle hook, the placeholder object UNINITIALIZED_VALUE is the previousValue. However, there is no easy way to check for that. You can do it by checking the constructor's name:

ExampleController.prototype.$onChanges = function (changes) {
    if (changes.expr.previousValue.constructor.name === 'UNINITIALIZED_VALUE') {
        // first time running
    }
};

but that seems like a bit of a hack.

The best solution I can think of is having the UNINITIALIZED_VALUE object should be stored as a constant (read-only) somewhere (eg angular.UNINITIALIZED_VALUE) to compare against, though there are probably other solutions as well.

Thanks!!

works as expected

Most helpful comment

Each change object (contained in the changes object) has an isFirstChange() method for this exact purpose.

All 5 comments

Each change object (contained in the changes object) has an isFirstChange() method for this exact purpose.

I used the following code as isFirstChange() is not available in the changes object:

ctrl.$onChanges = function (changesObj) { if (changesObj.fieldInfo.previousValue.constructor.name === 'UNINITIALIZED_VALUE') { init(); } };

@saurajit it doesn't look like it's there (eg in the Dev tools console it appears to be missing when hovering on change.expr object) but that function is hidden on the object's prototype. Try executing changes.expr.isFirstChange() (or in your example changesObj.fieldInfo.isFirstChange()).

I used the following code as isFirstChange() is not available in the changes object:

ctrl.$onChanges = function (changesObj) { if (changesObj.fieldInfo.previousValue.constructor.name === 'UNINITIALIZED_VALUE') { init(); } };

Sorry but this will not work with a minified bundle.

As mentioned in https://github.com/angular/angular.js/issues/14917#issuecomment-232971141, the isFirstChange() method is on every _object_ inside changes. So, in this case, it should be changesObj.fieldInfo.isFirstChange().

Was this page helpful?
0 / 5 - 0 ratings

Related issues

butchpeters picture butchpeters  ·  3Comments

kishanmundha picture kishanmundha  ·  3Comments

brijesh1ec picture brijesh1ec  ·  3Comments

jetta20162 picture jetta20162  ·  3Comments

tdumitrescu picture tdumitrescu  ·  3Comments