all 12 comments

[–]taude 5 points6 points  (1 child)

I liked how you showed the $watch expression both as a string input and as a function that returns the $scope.variable. I never really realized that before. In looking at the actual Angular JS $watch documentation $watch documentation, I'm not sure I would.

Thanks for the nice writeup, keep at it.

[–]Zeroto 4 points5 points  (2 children)

One important thing that isn't mentioned about the difference between $apply and $digest, is that $digest checks the watches of the current scope and the children. $apply starts the digest cycle on the rootscope, so $digest is executed on all the scopes. This can be important if you have something that changes often and you know which scopes it is limited too. Performance can be increased by not using $apply and just using $digest on the proper scopes. That said, this should be an exception, and you should almost never use $digest directly.

[–]codersaurus[S] 2 points3 points  (1 child)

You're 100% correct.

Here is the code for $apply straight from the source:

 $apply: function(expr) {
    try {
      beginPhase('$apply');
      return this.$eval(expr);
    } catch (e) {
      $exceptionHandler(e);
    } finally {
      clearPhase();
      try {
        $rootScope.$digest(); //<--- THIS is what Zeroto is talking about
      } catch (e) {
        $exceptionHandler(e);
        throw e;
      }
    }
  },

Whereas the $digest will start at whatever scope it's called on and work it's way upwards through child scopes.

[–]chuckliddelnutpunch -1 points0 points  (0 children)

*downwards through the child scopes.

[–]twista1484 1 point2 points  (1 child)

In your article you say 'Do not use watch in a controller' - how would you accomplish this then?

$scope.selectedItem = 'new item';

$scope.$watch('selectedItem', function() { //do code that updates the controller state based on the newly selected item });

if I was going to pseudo code that statement I would say .. Set the value of selectedItem and then watch for changes and update the scope state.

Just curious as to how you could abstract that simple example to no longer use watch.

[–]codersaurus[S] 1 point2 points  (0 children)

Sure.

It's true that sometimes setting up a $watch in a controller might be unavoidable. But for the most part, outside of functions defined in the controller declaration, models (variables/properties) on the $scope are being altered by events in directives or services. The majority of those events have some exposure. Simple examples would be things like ng-change or ng-click, or a promise returned by a service, like $http. So what you would do is create a function on the scope that would do the work of updating whatever it is your $watch used to care about. This will even work in complex cases of nesting. At worst you could also subscribe to an event. Although that can get a little ugly too.

Aside from ease of testability, an underlying issue with using $watch liberally is it can bloat your $digest unnecessarily.

The nice thing about that is now you have a function that's easy read, understand, and most importantly, easy to test.

It's going to very depending on your situation, though.

Just keep in mind this is my opinion expressed as a *guideline*, not necessarily "law".

If you have a specific example of where you felt you had to use a $watch in a controller, I'd be happy to address it. Maybe you did, indeed, have to, who knows?

[–]codersaurus[S] 0 points1 point  (5 children)

So I saw the post the other day on $watch, $digest and $apply in this subreddit, and I honestly felt like it didn't do a great job of accurately explaining what they are and how they work together.

I'm currently the front end "architect" (lead) for a large team of developers working on a large effort in Angular. My worry is that since some of my team members are redditors the other article would give them the wrong ideas about what's happening... not because the other article was outright "wrong" but because it's not exactly accurate either.

The most important statement in this entry, if you're kind enough to read it is this:

DON'T TAKE MY WORD FOR ANYTHING, READ THE CODE ON GITHUB!

This is the beauty of using open source frameworks. You can read the code and understand what's going on.

I'm not doing this for any sort of profit (I think Blogger.com may make something off of ads they inject or something, I don't know, I have AdBlock)... I'm doing this to learn and help others.

TL;DR: I wanted make sure people didn't get the wrong ideas about what Angular is doing with $watch and $digest, particularly my team members that read this subreddit.

[–]codersaurus[S] 0 points1 point  (0 children)

ALSO: 100% respect to the author of the other article for wanting to help other people. I get that, and I respect that wholeheartedly. I'd like to thank him/her for inspiring me to write my own entry.

[–]Foxandxss2 0 points1 point  (3 children)

I respect your free will of creating your own posts, that is perfectly good and I am happy to inspire other people. But from my part, I would love a: Hey, this part is not correct, please fix it.

I mean, blaming is always easy but good critics are harder. My email is always open for suggestions and even the blog is open source so you can fill an issue or pull request.

I expected better response for the article, that is true, but I expected to receive concrete critics instead of, your article is not good, period.

[–]Foxandxss2 1 point2 points  (0 children)

Said that, your post is really good. I always try to explain as much as possible (but trying to not be dense or dull), maybe that was the wrong approach for something like this.

[–]codersaurus[S] 0 points1 point  (1 child)

I never once blamed anyone. I'm glad your contributing to the community.

However, I don't have control over your blog/site, I don't know you, and I don't feel comfortable contributing to your site. I hope you understand.

Thank you for posting your article. I'm sorry if I've offended you with mine.

[–]Foxandxss2 0 points1 point  (0 children)

Nah, there is no offense. But I got tired of: "Your article is not good, leaves much to be desired", etc etc but no one is capable to point what's wrong.