I have a service loaded into a component as a provider. This service may return data using Http or it may not, the component should not care. However, it seems that the component itself must include HTTP_PROVIDERS if the loaded service uses Http. This breaks separation of concerns. What am I misunderstanding?
This breaks separation of concerns. What am I misunderstanding?
In order to support instantiating multiple instances of a service (i.e., so all services don't have to be singletons), an Angular app needs a way to specify multiple injectors (not just one). These injectors need to be created and configured in some kind of hierarchy. The component/directive tree, since it is a tree, already has a hierarchy. So Angular uses the (existing) component tree to configure dependency injection. I like to think of it as a sparser "injector tree" that overlays the component tree.
I think it would be more work to define a separate hierarchy for services – we, as developers, would probably have to define and configure another injector tree of some sort.
So instead of thinking of it as "components need to know the dependencies of services" (which, when stated that way, it does sound like we're breaking separation of concerns), I like to think of it more like the following: "when I write an Angular app, I have to configure my providers/dependencies on the injector tree"... and since the injector tree overlays the component tree, I use components to configure it.
But this is not ideal, since if you want to reuse components in a different app, you might need to change the providers arrays (i.e., you may need to reconfigure the injector tree).
In fact, it's better to specify the HTTP_PROVIDERS when bootstrapping your application:
bootstrap(AppComponent, [ HTTP_PROVIDERS ]);
But I agree with you that there are some impacts on having configuration of providers only on components.
The previous configuration will work because of hierarchical injectors.
See this question for more details about hierarchical injectors:
What's the best way to inject one service into another in angular 2 (Beta)?
Related
Summary
I am writing a React-Redux application, and would like to create a service that can be accessed across multiple components, with the following characteristics:
Singleton (just gets instantiated once across the entire
application)
Injectable (can be injected into, and used by, multiple components across the application)
Redux Connected (can access the entire Redux state tree & received updates to state changes)
Code Example
The type of solution I have in mind, would allow me to inject a service int a React Component, and use in the following way:
{ featureAvailabilityService.isAvailable('myFeature') && (<MyFeature />) }
Ideas
I have read about High Order Components, Hooks, and the Context API. There are also some interesting libraries, such as Unstated, and Redux-Logic. I feel like the best answer probably lies somewhere between these, but could use some guidance to put me on the right track.
Use Case
In this instance, I would like to create a reusable service, which has methods to determine the availability of certain features. This involves relatively complex logic based on System, Tenant, and User configuration and state. It also requires the service to have access to state from several different parts of the application. It will also be reused broadly across the application.
Why Yet Another React Service Question?
I realize there are already a lot of similar questions to this, usually from people with an Angular background, looking for the React equivalent to an Angular Service. However, I have not yet found an answer that provides for the above three criteria... or at least not one that I understood.
Thanks for any input.
All:
I am pretty new to React from AngularJS. In AngularJS, there is service dependency inject which can provide a service instance to do data fetching, processing, etc., other than UI operation. I wonder how to do this(or implement that injection) in React component?
Thanks
I prefer to create a service in another file that exposes the 'public' functions through module.exports.
e.g.
module.exports = {
foo: function(){ return bar; }
}
which is then referenced by Components using
import myService from './routetoservice/myService'
An Extension to Michael Dunn's Answer
This is the actual answer ,
Service pattern is not limited to any programming language or
library.
We can implement this concept in any language , Even we can
implement this in react
A tiny service can be created on server OR in ui browser in Javascript that serves some logical purpose
It gives us benefits of code availability, code management , code isolation of particular logic
Its a very native way for code availability, code management , code isolation of particular logic
If we compare redux/flux vs services ,redux/flux also serve these purpose's
Currently i am using redux and its actions , and also created my tiny services on ui when required.
No need to use OTHER NPM MODULES FOR CREATING SERVICES , Just Michael Dunn's solution is enough
In reactjs we use the flux pattern to provide data handling. Here is an example of that with reflux. React with Flux: is this the dogmatic pattern or are there equal/better options?.
React seems philosophically opposed to services in the Angular sense, apparently preferring tight coupling of UI and logic.
But I have found a react-services module, which seems to offer what you are after:
• separate your component and application state by introducing a service layer that takes care of propagating changes through your application
• manage component dependencies in an explicit, testable way
• there's no events and no lifecycle management - everything is done automatically for you
• it's tiny and easy to understand - the core is less than 100 lines of code
https://medium.com/#alshdavid/react-state-and-services-edb95be48851
Here's an article showing how to do it with nothing but React Context and rxjs
So I am just starting out with angularjs and web development in general and had a few questions regarding the best practices. Some of my questions are actually more related to web development in general.
1) When to use partials and when to use a different page instead. E.g Is is good to embed about.html as a partial in index.html or have a separate page?
2) What is the best way to share data between controllers? Right now I am using query parameters in the route.
3) Should I be using one controller for multiple partials?
Thanks!
Angular is a single page app framework, so you only want to use one html 'page' in most cases. There may be exceptions but unless your project is very large you won't need to use more than one.
Services are the recommended way of doing this. Services return a singleton object, and you can inject references to them using angular's dependency injection. It keeps everything modular, too. Query params are definitely not what you want to use. For calling events between controllers you might also use $scope.$broadcast().
Potentially, you might have an overall AppController for example that encompasses elements that have their own controllers (in their own directives, or using ng-controller). On the subject of directives, remember to use them to bundle re-usable components up. Directives have their own templates and controllers, and using them makes your code much more modular and easier to maintain/test.
tl;dr
I'm really struggling to find the appropriate pattern here. How should I best configure a generalized provider to a specific use-case? I can't use $http as a dependency in .configure(); can I?
longer, boring explanation:
I am trying to create a generalized provider which I may reuse in Angular. I have it working, however it requires configuration.
The intention is to provide a fallback REST service to use in saving data to the server, but with provision to save offline in local-storage. Therefore, I need to provide appropriate $http calls for each instance of this provider.
Is it possible to provide appropriate $http calls with .configure() or else should I try and figure out how to inject $http into the provider from the start and then configure it afterward??
It's frustrating... and may change in AngularJS 2.0... But for now, yes, it is not possible to do this. There is a very high wall between the .configure() and .run() states, so you can't access $http from a .configure() function. The reason is that it hasn't actually been created. At this stage, all that exists is the provider. Once all of the dependencies are configured, then the http provider will be used to make the real $http service.
I'm not sure exactly what you're trying to do, but there are two excellent AngularJS developers that are good to follow who have some advanced patterns in projects they've shared: Pascal Precht and Brian Ford. Here are two projects that make heavy use of provider/service concepts as well as $http-driven services:
https://github.com/angular-translate/angular-translate
https://github.com/btford/angular-modal
Angular Modal, especially, does $http work to load its templates. There might be use cases in there that are similar to what you're trying to do.
I have been reading a lot of docs, and I'm getting more and more confused.
I basically can't figure out the difference between a
service
directive
module
I see a lot of custom components. Sometimes they're using directives, sometimes services. It always starts with a module. Can someone explain with an example what the difference is between these three types?
From my own personal notes (mostly snippets from the docs, google group posts, and SO posts):
Modules
provide a way to namespace/group services, directives, filters, configuration information and initialization code
help avoid global variables
are used to configure the $injector, allowing the things defined by the module (or the whole module itself) to be injected elsewhere (Dependency Injection stuff)
Angular modules are not related to CommonJS or Require.js. As opposed to AMD or Require.js modules, Angular modules don't try to solve the problem of script load ordering or lazy script fetching. These goals are orthogonal and both module systems can live side by side and fulfill their goals (so the docs claim).
Services
are singletons, so there is only one instance of each service you define. As singletons, they are not affected by scopes, and hence can be accessed by (shared with) multiple views/controllers/directives/other services
You can (and probably should) create custom services when
two or more things need access to the same data (don't use root scope) or you just want to neatly encapsulate your data
you want to encapsulate interactions with, say, a web server (extend $resource or $http in your service)
Built-in services start with '$'.
To use a service, dependency injection is required on the dependent (e.g., on the controller, or another service, or a directive).
Directives (some of the items below say essentially the same thing, but I've found that sometimes a slightly different wording helps a lot)
are responsible for updating the DOM when the state of the model changes
extend HTML vocabulary = teach HTML new tricks. Angular comes with a built in set of directives (e.g., ng-* stuff) which are useful for building web applications but you can add your own such that HTML can be turned into a declarative Domain Specific Language (DSL). E.g., the <tabs> and <pane> elements on the Angular home page demo "Creating Components".
Non-obvious built-in directives (because they don't start with "ng"): a, form, input, script, select, textarea. Under Angular, these all do more than normal!
Directives allow you to "componentize HTML". Directives are often better than ng-include. E.g., when you start writing lots of HTML with mainly data-binding, refactor that HTML into (reusable) directives.
The Angular compiler allows you to attach behavior to any HTML element or attribute and even create new HTML elements or attributes with custom behavior. Angular calls these behavior extensions directives.
When you boil it all down, a directive is just a function which executes when the Angular compiler encounters it in the DOM.
A directive is a behavior or DOM transformation which is triggered by a presence of an attribute, an element name, a class name, or a name in a comment. Directive is a behavior which should be triggered when specific HTML constructs are encountered in the (HTML) compilation process. The directives can be placed in element names, attributes, class names, as well as comments.
Most directives are restricted to attribute only. E.g., DoubleClick only uses custom attribute directives.
see also What is an angularjs directive?
Define and group Angular things (dependency injection stuff) in modules.
Share data and wrap web server interaction in services.
Extend HTML and do DOM manipulation in directives.
And make Controllers as "thin" as possible.
Think of a module as being a place to wire up a number of other things, such as directives, services, constants etc. Modules can be injected into other modules giving you a high level of reuse.
When writing an angular app, you would have a top-level module which is your application code (without templates).
Services are mainly a way to communicate between controllers, but you can inject one service into another. Services are often used as a way to get to your data stores and people will wrap the angular APIs, such as ngResource. This technique is useful since it makes testing (particularly mocking) quite easy. You can have services for doing other things like authentication, logging etc.
Directives are used for creating widgets or wrapping existing things like jquery plugins. Wrapping existing plugins can be a challenge and the reason you would do this is to establish a two-way data binding between the plugins and angular. If you don't need two-way data binding then you don't need to wrap them.
A directive is also a place for doing DOM manipulation, catching DOM-events etc. You should not be doing DOM-related stuff in controllers or services. Creating directives can get pretty complex. IMHO, I recommend first looking at API for something that can do what you are looking for OR ask Angular's Google Group for advice.