Are factory and service instances of Declarative Programming in AngularJS - javascript

In Angular JS we declare services and factories. We create a service by declaring a function. We do not call the function ourselves.
Does this mean that is declarative programming. I suppose, the framework does the imperative work?
What is the imperative work being done in the background?

Yes, Angular does most of the imperative work (in your terms) that is related to lifecycle of instances. Here are some things that Angular do for you:
Each service, factory and provider in Angular that is declared by developer, provides angular with constructor function of that service, instance created by factory or constructor function that returns object having $get() method that returns an instance of provider. More about this see here.
All services in Angular are singletons that are instantiated only once (when first time injected to some controller, service, directive or whatever). That means that it is possible to share state using same service injected to different controllers as example.
Besides of it for each service/factory Angular creates provider with the same name as service/factory appended with word "Provider" behind the scenes.
Controllers, directives and filters are very similar to services, but need some special treatment (because of scope/input to be injected). For them Angular also creates a lot of useful staff.
If to say the truth, for about half a year working with Angular every day and night, I noticed that stopped to use new at all, just because there is no need any longer - Angular cares about creating and destroying instances.

Related

Component level service in AngularJs

I'm looking for a way to implement a component level service whose scope is limited to the component and not to the full application, so that for every instance of this component I'll have a separate instance of this service.
Tried creating a service and instantiated it using new keyword(not registered in angular module) in the controller but then I have to provide all the dependencies manually or have to use $injector to get the dependencies in this service class.
Also to make this approach testable I need to expose this property so that one can mock it.
Would like to know more cleaner approach to achieve this where I can inject it in the controller.
I know this is possible in Angular...but I have to achieve it in AngularJs.
Create an angular .factory instead of a .service, inject as normal and instantiate with a new factory() in component. You should be able to find many examples of creating an angular factory with prototypes and returning the factory function back.

Why would you ever use the $rootScope?

Ok so I was reading here
basically when I have this
MyApp = MyApp || {};
MyApp.settings = {
isFooEnabled: false
}
if I use the rootscope and want to check if isFooEnabled I have to inject the rootScope into whatever object I want to do the check.
How does that make sense?
What is the advantage of using $rootScope.isFooEnabled over using straight standard javascript MyApp.isFooEnabled?
what is better for what?
when should I use one over the other?
The $rootScope is the top-most scope. An app can have only one $rootScope which will be shared among all the components of an app. Hence it acts like a global variable. All other $scopes are children of the $rootScope.
The rootScope's variable is set when the module initializes, and then each of the inherited scope's get their own copy which can be set independently.
NOTE:
When you use ng-model with $rootScope objects then AngularJS updates those objects under a specific $scope of a controller but not
at global level $rootScope.
The $rootScope shouldn't be used to share variables when we have things like services and factories.
Finally, Angular FAQ says this at the bottom of the page: "Conversely, don't create a service whose only purpose in life is to store and return bits of data." See from here.
Actually, I would argue that you shouldn't use $rootScope in this case, you should create a separate service (or factory) that stores your settings, however, the usage and reasons are the same.
For simply storing values, the primary reason is consistency. Modules and dependency injection are a big part of angular to ensure you write testable code, and these all use dependency injection so that unit tests can be written easily (dependencies can be mocked). Whilst there are not many obvious gains from injecting a simple object, it's consistent with the way more complex code is accessed, and there is a lot to be said for that. On a similar note, if you were to upgrade your settings object to fetch data from the server (e.g. for environment specific settings), you might want to start unit testing that functionality, which you can't really do properly without modularising it.
There is also the (frankly weak) namespacing argument - what if another library you import uses window.MyApp?
TL;DR: It's a strongly recommended best-practice. It might seem a bit clunky now, but you'll benefit from doing it in the long run.

Isolate scopes angularjs, ditching dependency injection, reusable components

I haven't really been fiddling for angularjs's directive for a while and I do not still have a good grasp on it. Before I dive into it, I am thinking react, on how they do their components.
So I have search on how to create reusable components using directives, and found this article:
http://michalostruszka.pl/blog/2015/01/18/angular-directives-di/
But the implementation on his final solution is quite blurry, as I cannot figure out on how to use it correctly.
Let's say I create a title directive:
<epw-title store="epwEventStore">{{vm.title}}</epw-title>
And another directive that uses the same service epwEventStore so that it can update the state
<epw-event-list store="epwEventStore"></epw-event-list>
Where the epw-event-list renders a list and when clicked should change the value of vm.title of the epw-title.
How is this possible?
Update
Q: Are they nested?
A: No, they are siblings.
Don't put Services inside Views
Just to avoid any misunderstanding, if epwEventStore is an AngularJS Service (such as provider, factory, service), it is not meant to be put as attribute value inside your template like that:
<epw-title store="epwEventStore">{{vm.title}}</epw-title>
In a well-designed decoupled architecture, your Views (template) should not "know" anything about your Services. They should only refer to controllers, directives and filters.
Different directives can use the same service
That means you can perfectly have
...
.directive("first", function(myService) {
...
})
.directive("two", function(myService) {
...
})
...
where, e.g., both directive can access and manipulate the same data.
Angular way is declarative
Following Angular's philosophy, if your directive depends on a Service, you declare it in the directive's definition. So whoever reads the code - knows immediately about all dependencies. This makes the code readable.
What the author of the article seems to be suggesting is to use events instead. Which is the publish-subscribe pattern. However, using it inside your directive, especially with $rootScope, makes the directive "leaky" as it is no more encapsulated and can both affect the external state and be affected. And worse - the reader has now manually search all your codebase for whoever is affected by the events emitted from the directive. This pattern has its uses but should be enjoyed with care.

Angular practice - using scope inheritance vs injection

I have a question that came up in a meeting that I would like to get some expert opinion on.
lets say I have a 'userService' that many controllers in my app need. (in fact most of them).
It was my belief that any parent controllers would inject this userService and expose properties of that service to child controllers. Since any 'child' controllers have access to parent scope, there is no need to inject the 'userService' into every controller.
Another person's opinion was to inject the 'userService' into every controller that needs it, regardless if the service is already inherited from it's parent, basically because it makes the code easier to read and easy to find where your variables are coming from.
To me, this view seems wrong, and misses the point of Angular and how it uses prototype inheritance, and the power of scope. Doesn't this actually create unnecessary instances in memory that reference the same thing ? why would you want to do that ?
I would love to hear some experience opinions on this.
Thanks!
The references in memory are cheap. Don't worry about those. More importantly, you're implicitly creating a dependency that leads to a non-reusable component when you put something on scope that a child needs to do its' job. You should instead declare your dependencies upfront--via the argument list. You'll thank yourself later when you come to testing. Scope inheritance is for templates--not controllers.
There's some arguments both ways, but I avoid scope inheritance whenever possible. I even isolate scopes on most of my directives. The reason is that you can more naturally de-couple and encapsulate your code. Encapsulation is less of a problem on controllers in general, but it's nice to know that wherever you are in a scope hierarchy you can always get to your service.
Someone can correct me if I'm wrong, but I think it works like this.
Controller A injects service A. It can access it via A.method
Controller B inherits from Controller A but cannot access service A as it doesn't know what it is.
Scope inheritance comes into play when you assign that service to a scope variable. If we change it now so that Controller A sets $scope.A = A THEN Controller B will be able to access the service via $scope.A.method as it has inherited this.
I don't think the injected services themselves are inherited.
In terms of memory, I wouldn't worry too much. Angular won't be creating a new instance, just a reference to it. Services are singletons and won't get recreated unless they're destroyed. If you're using Factories, then you may get new objects but that's different.

Service functions outside Angularjs scope

I have created a service in angularJS that uses btford.socket-io module to interact with the server.
Since in the service I have implemented some API that I use inside angular at the moment, but for later extension of the application I also need to give access to these API outside angular scope.
So that in future one could just call the function without having the need to create controller and other stuff.
At the moment I did this for a controller
var myController = angular.element($('body')).scope().myController;
by saving the whole controller inside a scope variable.
I was wondering if it would be possible to do the same with a service.
How about:
angular.element(document.body).injector().get('MyService');
Typically not good practice. But sometimes its needed.
Note: document.body is the element Your angular application is mounted to
Another thing you might consider is 'closing' external api with angular via a factory.
eg. return your global or namespaced class or api from an angular factory.
This is essentially what angular does for you. But instead of creating the reference inside angular first and having to extract it, you'd create it outside, and register it with DI as a factory or value.

Categories

Resources