is there any differences between $scope.$watch and $watch? - javascript

I was learning angular. i didn't get anyhitng from angular documentation can anyone please tell me what is $watch
what does it happens if we change that to $scope.$watch
sorry i'm new to the anguar this question seem like bit silly....if i'm wrong in knowledge

There is not stand alone $watch service. People are saying $watch instead of $scope.$watch but it's the same. it's just longer to say $scope.$watch, and it's just to mention that even if it's related to $scope he's like a whole new service.
But I may be wrong there's maybe an external stand alone service who's name is $watch, but I don't think so.

if you watch an expression, you need a context that is used to resolve it. Consider
$watch("foo", handler);
how should angular know what foo to watch? It makes only sense in the context of a scope
somescope.$watch("foo", handler);
so angular know what foo to watch.
But if you are talking about watches in general, many people omit the scope for the sake of simplicity. But you should know: You can't watch for something if you don't know where to watch ;)

Related

Factories calling their own functions

I've recently ran into a factory that vaguely resembles the one shown below:
.factory("MyFactory", ['$interval', function($interval) {
var factoryObj;
factoryObj.setCheckupTime = function(intervalMs) {
var checkupInterval = $interval(function() {
// do checkup logic...
}, intervalMs);
};
factoryObj.setCheckupTime(60000);
return factoryObj;
}]);
The problem is the line right before the return:
factoryObj.setCheckupTime(60000);
This line feels wrong because we're making a singleton perform an action on itself automatically instead of by some dependent unit of code.
I wanted to get others' opinions on the matter; does this go formally go against any of Angular's best practices, or maybe any rules on how Singletons are supposed to be used?
I was also unsure how to describe this problem as I've never ran into it; is there another term/terminology for what's going on here?
So, is it a bad idea declaring a factory that self starts it's own thing when it's built by angular's core not telling anybody that something has started in the process?
Yes, that's really bad! Is really difficult to maintain and track problems when things are done automatically especially on angular factory that is an internal behavior.
I recommend starting it manually from somewhere that you can track and understand it in the future.

Using a service for small task

i been reading about services or factories in angularjs, but im having some trouble finding the best solution, basically i need to pass some data from one controller to another controller, it is a boolean value, but i dont want to create a service for just a small task.
I believe that wouldnt make much sense for just a small job. is there other way in angularjs for this type of situations? Where i could pass small data between controllers. I been looking around in angularjs documentation, but cant figure out the best solution.
Use $rootScope.emit()
in Controller A
$rootScope.emit('toggle',true);
in Controller B
$rootScope.on('toggle', function(value){
})
For tiny items, you could use parameters. The the end user, they'd look like a part of the URL string. This is avaible with and without using ngRoute. Have a look at this stack question.
For more complex data or data that's unsuitable to displaying to an end user, use a service or factory. Seems like overkill, but it gives you greater flexibility.
A $broadcast/$on pattern just gets messy and harder to troubleshoot.
If it's parent/children controller, you can transfer your value with $scope or $emit/$broadcast.
If controllers are on the same level(siblings) you can make wrapper controller for them to store shared data.
If you think there would be similar requirements for other tasks you can consider service, and making it abstract and reusable(some sort of helper).
In any way, you didn't provide enough of info, and there could be a lot of solutions until we see real example.
If your controllers have a child parent relationship (in any level) then you can try with $broadcast or $emmit to throw the data and $on to catch that with a a event. Otherwise inject $rootScope to one of them and trigger either $broadCast on the monitor of $rootScope, or $emmit on the monitor of $scope and catch thet data using $on('eventName', function(ev, data){}) correspondingly.

How angular js watches mutations in object?

I am curious to know how angular js watches mutations which happens to a property added to $scope. From HTML point of view, I am able to get it, that we have some events which are fired whenever there's a change. But when it's regarding an object I am not able to understand how it actually works. I can see we have a function called Object.observe. But that is also deprecated as written here. And I am pretty much sure that angular does not use Object.observe. The doc of angular says that one can watch mutations using $watch and $watchCollection. But I am not able to get how these are notified. Can anyone help on this?
Angular will actually take a copy of the object being watched and compare against it every digest loop. So there are no notification when things change. It looks for changes every loop. And that's why watching can be expensive. The more watches you have, the more comparisons needs to be made, and in the case where changes are found, you might end up with a new run to make sure that the change that was detected doesn't affect one of the watched objects that you already checked.
I would suggest the book 'Build you own AngularJS' by Tero Parviainen. Even though it's not a 100% accurate source recreation, the concepts are the same, and you'll get good insight in how angular works.
Another source for understanding this part of angular is the chapter 'The Digest Loop and $apply' of the 'ng-book'. The concept is described there in a more 'accessible' form than in Teros book.

Models implemented as Scopes in Angular

I have this situation now where I’ve implement models as a plain JavaScript object. So you can synchronously ask the model for a value and you can subscribe to event to get notified about updates to the model. But I’m not happy doing it this way. It leads to a lot of code and checks everywhere.
Now, I’ve been thinking, wouldn’t it be better to make use of Angular and use isolated scopes for the models? This way anyone interested in a particular value can just watch the model for changes.
Example:
function UserService($rootScope) {
var model = $rootScope.$new(true);
this.getModel = function() {
return model;
};
}
function userWidget(userService) {
var user = userService.getModel();
user.$watch('isLoggedIn', function(isLoggedIn) {
//React to if the user i signed in or not...
});
}
Is it a good idea or a bad idea? Any thoughts about this? How have you solved this?
Even if silly, here is a small demo:
http://plnkr.co/edit/JTggQ0FVYpo4saLmjLAo
Thanks!
/Martin
There's nothing wrong with it, but I would personally have a benefit to describe before I just randomly did that. $rootScope.$new is actually sort of heavy - an AngularJS scope has a lot of additional reference objects like siblings and parents. If you have 5, who cares? But if you have 5,000 that's going to be heavy for the garbage collector to manage. It's totally justified if it gives you some advantage, but if it's just for the sake of itself I wouldn't bother.
Is there a reason you rely on variable hoisting so much in your example? It's usually viewed as a by-product or anti-pattern, so it may throw off other developers who help maintain your code. Or are you flying solo? :)

How to bind an Angular's controller function using javascript

Is there a way in AngularJS to programmatically bind a controller method using only javascript(instead of using ng-* markup)?
Something like
$("#foo").click(FooController.foo)
PS: I don't have access to $compile
Do you really need controller's methods or scope's?
in case if you need scope's you can use angular.element('#myid').scope().method
But please keep in mind that any modification of scope's values are not detected if you do them outside of AngularJS event processing, so you need to wrap your code into $apply function of scope.
Also keep in mind that in AngularJS DOM modifications from JS are generally "big no no"
Ofcourse there are controller's functions (created using "this.xxx = function () .."). I am not sure that it is good to access them as they are kind of private, but you should be able to access same way: element(..).controller().method
It is not officially supported. For sure it is technically possible with some hacks but binding event handlers from JavaScript would mean getting access to a DOM element from a controller and it goes against principles of AngularJS.
To extend #Valentyn's answer somewhat, if you had wanted to access a controller method (and not a $scope method) -- e.g., a method defined with this in the controller constructor function (on the Angular homepage, the "tabs" directive defines function "addPane" on the controller using this) -- you can use
angular.element('#myid').controller().method()
You can, but you shouldn't. You'll likely run into trouble down the road.
If you can give a bit more explanation as to why you want to do this, there might be a better (and easier) method.

Categories