2

wondering if there is a way in angular to watch a function like you would a variable

function foo() {
    console.log("foo called");
}

$scope.$watch('foo', function {
    console.log("foo watched");
});

So given the syntax is correct, will "foo watched" be printed to the console, if not, is there a way to have that watch function run?

EDIT

Reformatting question to more of what I need:

Let's say I have a button and an text input, each handled by different controllers, say btnCtrl and txtCtrl

There is also a boolean global flag stored as $scope.flag which changes the validation standards for the input.

//btnCtrl

//called on button click
function onButtonClick() {
    $scope.flag = !$scope.flag
}

//txtCtrl

//called on input change
function onInputChange() {
    handleValidations()
}

function handleValidations() {
    //set error indicator on invalid input
    //valid input changes based on $scope.flag value
    if($scope.flag) {
        //check validation1
    } else {
        //check validation2
    }
}

I want to check the input box validations, handleValidations when $scope.flag is changed. $scope.flag is changed frequently not by the button, but by other functions.

So, I would like to call handleValidations not when $scope.flag is changed, but when onButtonClick is called. What is the best way to do that?

My initial thought was to put some sort of $scope.$watch on onButtonClick.

Conor
  • 21
  • 5
  • 1
    Why can't you just invoke another one function inside `foo`? – P.S. Jan 17 '18 at 15:40
  • 1
    If you want to know if the function `foo` was fired, you can call [`$rootScope.$broadcast`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast) inside it and listen for that event with [`$scope.$on`](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on) – Aleksey Solovey Jan 17 '18 at 15:42
  • @AlekseySolovey That would work but trying to limit number of `$rootscope` calls, do you think there's another way? – Conor Jan 17 '18 at 15:51
  • @CommercialSuicide The `$watch` is in a controller and `foo` is in a model. `foo` is only invoked on a button press handled by a different controller. – Conor Jan 17 '18 at 15:57
  • 1
    @ConorMaley it [would be best](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) if you can **describe what you want to do** in the first place. Perhaps you want to execute function `bar` after `foo`, then you can chain them with [`$q` promises](https://docs.angularjs.org/api/ng/service/$q) – Aleksey Solovey Jan 17 '18 at 15:57
  • @AlekseySolovey Yes, I was not specific enough, editing the post now – Conor Jan 17 '18 at 16:07
  • @ConorMaley I think it's the typical case of [this question](https://stackoverflow.com/questions/21919962/share-data-between-angularjs-controllers). Services are running in a different _layer_ and therefore can allow your controllers to communicate and share common variables. You should possibly change the code to have `YourService.flag = !YourService.flag` and `if(YourService.flag){...}` – Aleksey Solovey Jan 18 '18 at 11:29
  • @AlekseySolovey Yes that is another option, I am in too deep with the number of functions that touch the flag, so in hindsight, I should've done some better architecture-ing. The broadcast/listening approach you first suggested worked for me. Thanks! – Conor Jan 18 '18 at 15:49

2 Answers2

1

You can watch the functions. Have you tried running your code? If you call foo, it should print both console statements. There is a 'gotcha' for watching functions though, mastering $watch in Angularjs

One key aspect to note here, is that if the expression is evaluated as a function, then that function needs to be idempotent. In other words, for the same set of inputs it should always return the same output. If this is not the case, Angular will assume that the data being watched has changed. In turn, this means that it will keep detecting a difference and call the listener at every iteration of the digest cycle.

Tyler
  • 1,029
  • 1
  • 8
  • 20
0

With the help of the comments and other answers:

I sent a local message using $rootscope from btnCtrl and added a listener to txtCtrl that calls handleValidations

Thank you all for the help

Conor
  • 21
  • 5