Peter Boomsma
Peter Boomsma

Reputation: 9808

$watch is only working without a watchExpression

In my $onInit I have a $watch:

public $onInit() {
    const name = this.$state.current.name;
    console.log(name);
    this.$scope.$watch(name, (oldVal, newVal) => {
        console.log(oldVal, newVal);
        console.log(this.$state.current.name;
    });
}

When I run this code the oldVal, newVal are both undefined and the this.$state.current.name value is the same in the scope of the $watch and outside of it.

When I run the code without the name expression:

public $onInit() {
    const name = this.$state.current.name;
    console.log(name);
    this.$scope.$watch((oldVal, newVal) => {
        console.log(oldVal, newVal);
        console.log(this.$state.current.name);
    });
}

The $watch constantly runs. The oldVal is Scope {$id: 353, .... etc but the newVal is undefined. But the this.$state.current.name is now updated inside the $watch scope.

So the value of this.$scope.current.name does change. But when I use that as the expression in the $watch the oldVal, newVal are both undefined and the this.$state.current.name isn't changed inside the $watch.

It looks like I'm doing something wrong in the watchExpression. Any suggestions?

Upvotes: 2

Views: 31

Answers (2)

SylvainF
SylvainF

Reputation: 229

The watchExpression should be set as a string (even if it is already a string) Did you try this ?

var name = 'some value'
this.$scope.$watch('name', (oldVal, newVal) => {
    console.log(oldVal, newVal);
    console.log(this.$state.current.name);
});

Documentation

Upvotes: 0

Pankaj Parkar
Pankaj Parkar

Reputation: 136144

This is expected behaviour $watch function.

From docs

$watch(watchExpression, listener, [objectEquality]);
// watchExpression - can be `expression/function` 
// listener - callback
// objectEquality - deepWatch

$watch function evaluate its expression wrt $scope on each digest cycle run. So in the first approach you're just passing name as string, so what happens is, when digest cycle kicks in, it tries to evaluate name variable, which obviously not exist in $scope, that's the reason you're getting undefined value for each $watch evaluation.

Whereas in 2nd approach you're passing function/callback to $watch function. which evaluates on each digest cycle run, which is wrong. What you supposed to do is, pass callback function that will return this.$state.current.name, then only you will get desired results in $watch listener function.


It can be solved using below

this.$scope.$watch(() => {
   return this.$state.current.name
}, (oldVal, newVal) => {
    console.log(oldVal, newVal);
    console.log(this.$state.current.name;
});

Upvotes: 2

Related Questions