Component level service in AngularJs - javascript

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.

Related

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.

call a directive from a service angularjs + typescript

I am trying to call a directive from a service. I have implemented everything but my service scope is coming up empty. Normaly my functions are calling a directive from a controller. But these functions are now needed across multiple controllers so I want to put them in a service. Problem is my service cant see the functions in the directive even after doing dependency injection of the directive into the service.
export interface MyServiceScope extends IScope, directives.MyPanelScope, directives.MyPanelMenuScope {
// a bunch of properties that are not visible in the service scope, only the controller
}
// constructor here, controller does not initialize directives here just in interface and it works fine.
public serviceFunc() {
this.scope.panel.directiveFunc({ // directiveFunc undefined in service, but not in controller
template: "some/html/template",
data: {
item: data
}
});
}
So what do I do about getting the service to see the directive and call its functions?
You cannot inject a directive into a service n Angular. Actually you cannot inject a directive anywhere.
Directives are supposed to be a set of functions that strictly relate to specific DOM elements, and it is usually bad practice to use them to share code between different parts of the app. That purpose can be fulfilled by services.
If you find yourself in the situation where a service needs to call some function from a directive, I suggest that you review your code structure. I don't know the specifics of your case, but you could take the "shared" logic out of your directive into a service, inject that service into the directive and call it from there. In this way the logic called by the directive will be available to be injected to other parts of the application as well.

AngularJs - Why directives like Angular-strap and UI-Bootstrap use providers to build their compotents

I am planning to build my first complex directive, which is a component that lets the user crop and rotate an image that is provided and returns it as a Blob or Base64 string. I have been studying how other people have done it and I have used Angular-strap and UI-Bootstrap as a guide for understanding how to build efficient directives and ways to organize my code.
What has me confused is that components like the Modal and Alert use a Provider to build the component and return it, and in the directive it uses such provider to generate the content on compile, while other components like Tabs use a combination of a single controller for all the logic and a set of one or many directives and sub-directives that use such controller to build on compile.
So why do they use a Provider approach on some components and a Controller approach on others?
What are the benefits of building all the logic inside a Provider than in a Controller?
Another thing I've notices that their directives accept options through data attributes, which they parse on compile, why don't they use the directives scope to set global options?
Writing a provider and then using it in a directive has the added benefit of being able to use the provided features programatically.

Are factory and service instances of Declarative Programming in AngularJS

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.

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