Uncertainty about the use of services in AngularJS - angularjs

I have one question about using of services. I'm creating services in this way
and everything working properly. Here is my code.
var appName = angular.module('appName', ['configuration', 'angularSpinner']);
// this is whay that I creating services.
(function (module) {
var moduleName = function () {
return function(inputVar) {
// some work with
// inputVal variable
return result;
}
};
module.factory("moduleName", [moduleName]);
}(angular.module("appName")));
// in this way I'm using service into controller.
appName.controller('controllerName', function($scope, moduleName) {
});
My question is do I need to set 'moduleName' in 'appName'. Ie like this:
var appName = angular.module('appName', ['configuration', 'angularSpinner', 'moduleName']);
In both cases everything works properly. I would appreciate any comments and recommendations.
Best regards.

My question is do I need to set 'moduleName' in 'appName'. Ie like this:
No you do not, unless you actually create another module. In this case your moduleName is actually your factory name. If you wanted to create another module you would do this.
var myModule = angular.module('myModule', []);
myModule.factory('myFactory', [function(){ /* factory definition */ }]);
var app = angular.module('app', ['myModule']);
// this will now make myFactory available to my app
Your using the factory method which returns a function. If you need a service (a singleton object) then use the service method.
I create my services like this
var app = angular.module('app', []);
app.service('myService', [function(){
var serviceMember = { name: 'something' };
var serviceMethod = function() { };
// revealing module pattern
return {
serviceMember: serviceMember,
serviceMethod: serviceMethod
};
}]);

Yes, You needed
var appName = angular.module('appName', ['configuration', 'angularSpinner', 'moduleName'])
The 'appName' is Main Module name, and the 'moduleName' is sub module name. If you put the 'moduleName' with 'appName', then you can call 'modulname' functions wherever you use the 'appName'.
Main Module :
angular.module('appName',
Sub Module :
, ['configuration', 'angularSpinner', 'moduleName']
The concepts works by Dependency Injection Concept

Related

Two nested angular apps and constants

I have a main app:
var mainApp = angular.module('mainApp', ['secondApp'])
.constant('config', {
key: "mainKey"
});
And the second app looks like this:
var secondApp = angular.module('secondApp', [])
.constant('config', {
key: "secondKey"
});
When I am injecting config into a directive in the second app:
secondApp.directive("ngTest", function (config) {
});
config is being initialized from the main app config. What I am doing wrong here? When I name a constant differently and injecting with the different name it works fine.
var secondApp = angular.module('secondApp', [])
.constant('secondConfig', {
key: "secondKey"
});
secondApp.directive("ngTest", function (secondConfig) {
});
Version is: AngularJS v1.5.7
AngularJs 1 not does not handle namespace collisions.
So if you are using two module in one APP having same named
Services
Factory
Constants
So according to me best to overcome this problem is:
Just give some prefix to your variable
Like::
var mainApp = angular.module('mainApp', ['secondApp'])
.constant('mainApp_config', {
key: "mainKey"
});
var secondApp = angular.module('secondApp', [])
.constant('secondApp_config', {
key: "secondKey"
});
I know this is not a solution which may you are looking...
this is only way I know i can suggest to you.

Issues injecting Angular factories and services

I don't know what it is about injecting factories, but I am having the most difficult time.
I've simulated what I'm attempting to do via this sample plunk http://plnkr.co/edit/I6MJRx?p=preview, which creates a kendo treelist - it works fine.
I have an onChange event in script.js which just writes to the console. That's also working.
My plunk loads the following:
1) Inits the app module, and creates the main controller myCtrl (script.js)
2) Injects widgetLinkingFactory int myCtrl
3) Injects MyService into widgetLinkingFactory
The order in which I load the files in index.html appears to be VERY important.
Again, the above plunk is NOT the real application. It demonstrates how I'm injecting factories and services.
My actual code is giving me grief. I'm having much trouble inject factories/services into other factories.
For example,
when debugging inside function linking() below, I can see neither 'CalculatorService' nor 'MyService' services. However, I can see the 'reportsContext' service.
(function () {
// ******************************
// Factory: 'widgetLinkingFactory'
// ******************************
'use strict';
app.factory('widgetLinkingFactory', ['reportsContext', 'MyService', linking]);
function linking(reportsContext, MyService) {
var service = {
linkCharts: linkCharts
};
return service;
function linkCharts(parId, widgets, parentWidgetData) {
// *** WHEN DEBUGGING HERE, ***
// I CANNOT SEE 'CalculatorService' AND 'MyService'
// HOWEVER I CAN SEE 'reportsContext'
if (parentWidgetData.parentObj === undefined) {
// user clicked on root node of grid/treelist
}
_.each(widgets, function (wid) {
if (wid.dataModelOptions.linkedParentWidget) {
// REFRESH HERE...
}
});
}
}
})();
A snippet of reportsContext'service :
(function () {
'use strict';
var app = angular.module('rage');
app.service('reportsContext', ['$http', reportsContext]);
function reportsContext($http) {
this.encodeRageURL = function (sourceURL) {
var encodedURL = sourceURL.replace(/ /g, "%20");
encodedURL = encodedURL.replace(/</g, "%3C");
encodedURL = encodedURL.replace(/>/g, "%3E");
return encodedURL;
}
// SAVE CHART DATA TO LOCAL CACHE
this.saveChartCategoryAxisToLocalStorage = function (data) {
window.localStorage.setItem("chartCategoryAxis", JSON.stringify(data));
}
}
})();
One other point is that in my main directive code, I can a $broadcast event which calls the WidgetLinking factory :
Notice how I'm passing in the widgetLinkingFactory in scope.$on. Is this a problem ?
// Called from my DataModel factory :
$rootScope.$broadcast('refreshLinkedWidgets', id, widgetLinkingFactory, dataModelOptions);
// Watcher setup in my directive code :
scope.$on('refreshLinkedWidgets', function (event, parentWidgetId, widgetLinkingFactory, dataModelOptions) {
widgetLinkingFactory.linkCharts(parentWidgetId, scope.widgets, dataModelOptions);
});
I am wasting a lot of time with these injections, and it's driving me crazy.
Thanks ahead of time for your assistance.
regards,
Bob
I think you might want to read up on factories/services, but the following will work:
var app = angular.module('rage')
app.factory('hi', [function(){
var service = {};
service.sayHi = function(){return 'hi'}
return service;
}];
app.factory('bye', [function(){
var service = {};
service.sayBye = function(){return 'bye'}
return service;
}];
app.factory('combine', ['hi', 'bye', function(hi, bye){
var service = {};
service.sayHi = hi.sayHi;
service.sayBye = bye.sayBye;
return service;
}];
And in controller...
app.controller('test', ['combine', function(combine){
console.log(combine.sayHi());
console.log(combine.sayBye());
}];
So it would be most helpful if you created a plunk or something where we could fork your code and test a fix. Looking over your services it doen't seem that they are returning anything. I typically set up all of my services using the "factory" method as shown below
var app = angular.module('Bret.ApiM', ['ngRoute', 'angularFileUpload']);
app.factory('Bret.Api', ['$http', function ($http: ng.IHttpService) {
var adminService = new Bret.Api($http);
return adminService;
}]);
As you can see I give it a name and define what services it needs and then I create an object that is my service and return it to be consumed by something else. The above syntax is TypeScript which plays very nice with Angular as that is what the Angular team uses.

How to share factory from a parent module to a child module?

I have a parent module set up like so:
var app = angular.module("App", ["App.ClsEditor", "App.ClsNotes"]);
app.factory("Helpers", function($sce) {
var factory = {};
factory.createHtmlFromMarkdown = function(givenMarkdown) {
var escapedHtml = $sce.trustAsHtml(marked(givenMarkdown));
return escapedHtml;
}
return factory;
});
I have a submodule also defined like so:
var ClsNotesApp = angular.module("App.ClsNotes", ["ngRoute"]);
ClsNotesApp.controller("NotesCtrl", function($scope, $http, $routeParams, Helpers) {
$http.get("https://raw.githubusercontent.com/arun-curriculum/Advanced-JavaScript-Two-Day/master/day_1/README.md")
.then(function(data) {
var markdown = data.data;
$scope.output_html = Helpers.createHtmlFromMarkdown(markdown);
Helpers.highlightMarkdown();
});
});
It would make sense to me that the "Helpers" factory would be immediately accessible by the child module (App.ClsNotes). I get an error instead:
Unknown provider: HelpersProvider <- Helpers <- NotesCtrl
Any ideas?
I'd suggest you to create a separate angular modules like here you can say it as App.Utils that can have the multiple components in it like factory, service, filters, etc. By making a new module will be easier to inject it in any of module & the code separation rule also get followed by doing this.
Code
var utils = angular.module("App.Utils", ["ngSanitize"]);
utils.factory("Helpers", function($sce) {
var factory = {};
factory.createHtmlFromMarkdown = function(givenMarkdown) {
var escapedHtml = $sce.trustAsHtml(marked(givenMarkdown));
return escapedHtml;
}
return factory;
});
Then the controller module will include the App.Utils
var ClsNotesApp = angular.module("App.ClsNotes", ["ngRoute", "App.Utils"]);
You are requiring the App.ClsNotes module in your App module. If App.ClsNotes requires Helpers from the App, this becomes a circular dependency.
If you have helper methods, they should have no other dependencies from the app, though it is fine if they depend on externals.
This way, any module which depends on these helpers may specify the dependency without the risk of circular dependencies.

Separating scripts in Angular

I've created an angular app that has the following structure.
Application configuration, routes, directives, controllers and filters are all defined in index.js (I know this is not recommended). All of my general functions are in a controller called main.js, this is also the controller I am using in my main view in index.html. From then on the app consists of 10 different views, each has it's own controller.
main.js has become very difficult to maintain, so I would like to separate it into five external "utility" style files that contain the general function the application uses. These functions all use angular's $scope and must be able to be accessed by all the views and controllers that exist in the application.
For the past few days I've tried several different methods, such as defining the functions under angular's factory service, using angular's $provide method, defining a controller without a view and many others. None of them worked for me. What is the simplest way to separate the functions that exist in main.js to external js files without changing any code within the functions themselves. Let's pretend that the function cannot be turned into a directive.
Example -
Function that checks users name for 'guest' string and returns an image
main.js -
$scope.defaultpic = function(username) {
var guest = username;
if (guest.indexOf("guest") != -1){
{return {"background-image": "url('data:image/png;base64,chars"}}
}
}
in the view
<img ng-style="defaultpic(JSON.Value)" class="user_pic" ng-src="getprofilepic/{{JSON.Value}}"/>
Cheers,
Gidon
In order to use the function in markup, you still have to bind it to the scope. But, you can move the body of the function to a service:
angular.module('myapp').factory('picService',[ function () {
return {
defaultpic: function(username) {
var guest = username;
if (guest.indexOf("guest") != -1){
{return {"background-image": "url('data:image/png;base64,chars"}}
}
}
};
}]);
And then bind it up in the controller:
$scope.defaultpic = picService.defaultpic;
Refactor controller functions as services declared in different files
As you correctly stated, a great approach to refactor the functions is to put them into different services.
According to the angular Service docs:
Angular services are singletons objects or functions that carry out specific tasks common to web apps.
Here is an example:
Original code
Here we have a simple Hello World app, with a controller that has two functions: greet() and getName().
app.js
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.getName = function () {
return 'World';
}
$scope.greet = function (name) {
return 'Hello ' + name;
};
});
index.html
...
<div id="container" ng-controller="MainCtrl">
<h1>{{greet(getName())}}</h1>
</div>
...
We want to test that our scope always has both functions, so we know it is working as intended, so we are going to write two simple jasmine tests:
appSpec.js
describe('Testing a Hello World controller', function() {
var $scope = null;
var ctrl = null;
//you need to indicate your module in a test
beforeEach(module('plunker'));
beforeEach(inject(function($rootScope, $controller) {
$scope = $rootScope.$new();
ctrl = $controller('MainCtrl', {
$scope: $scope
});
}));
it('should say hallo to the World', function() {
expect($scope.getName()).toEqual('World');
});
it('shuld greet the correct person', function () {
expect($scope.greet('Jon Snow')).toEqual('Hello Jon Snow');
})
});
Check it out in plnkr
Step 1: Refactor controller functions into separate functions
In order to start decoupling our controller to our functions we are going to make two individual functions inside app.js.
app.js
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.getName = getName;
$scope.greet = greet;
});
function getName() {
return 'World';
}
function greet(name) {
return 'Hello ' + name;
}
Now we check our test output and we see that everything is working perfectly.
Check out the plnkr for step 1
Step 2: Move functions to their own services
We will define a NameService and GreetService, put our functions in them and then define the services as dependencies in our controller.
app.js
var app = angular.module('plunker', []);
app.service('NameService', function () {
this.getName = function getName() {
return 'World';
};
});
app.service('GreetService', function() {
this.greet = function greet(name) {
return 'Hello ' + name;
}
});
app.controller('MainCtrl', ['$scope', 'NameService', 'GreetService', function($scope, NameService, GreetService) {
$scope.getName = NameService.getName;
$scope.greet = GreetService.greet;
}]);
We make sure that our tests are still green, so we can move on to the final step.
Have a look at step 2 in plunker
Final Step: Put our services in different files
Finally we will make two files, NameService.js and GreetService.js and put our services in them.
NameService.js
angular.module('plunker').service('NameService', function () {
this.getName = function getName() {
return 'World';
};
});
GreetService.js
angular.module('plunker').service('GreetService', function() {
this.greet = function greet(name) {
return 'Hello ' + name;
}
});
We also need to make sure to add the new scripts to our index.html
index.html
...
<script src="NameService.js"></script>
<script src="GreetService.js"></script>
...
This is how our controller looks like now, neat huh?
app.js
var app = angular.module('plunker', []);
app.controller('MainCtrl', ['$scope', 'NameService', 'GreetService', function($scope, NameService, GreetService) {
$scope.getName = NameService.getName;
$scope.greet = GreetService.greet;
}]);
Plunker for the final step.
And that's it! Our tests still pass, so we know everything works like a charm.

Inject a config in AngularJS

I have a config that I'd like to be able to inject into Angular services, directives, etc. What is the best way to go about doing this?
I was playing with the idea of making config module:
'use strict';
angular.module('config', [])
But I wasn't sure how to construct the object literal that would be the actual config object that gets injected:
angular.module('myModule', ['ngResource', 'config'])
.factory('myservice', function ($resource) {
return $resource(config.myservice,{}, {
// whatever
})
});
Would it be okay to just expose config as a service and inject that?
I would say, the strategy varies, depending on what sort of config you have, but you have several options:
Module wide constants
If you only need several constants, you can use .value(), like this:
var app;
app = angular.module("my.angular.module", []);
app.value("baseUrl", "http://myrestservice.com/api/v1");
//injecting the value
app.controller("MyCtrl", ['baseUrl', function (baseUrl) {
console.log(baseUrl); // => "http://myrestservice.com/api/v1"
}]);
See a more detailed answer here.
Fetching the config/config service
What i personally like to do is fetch my configuration from somewhere else via a service just as normal. It doesn't matter, if this is a remote location or just static information.
var app;
app = angular.module("my.angular.config", []);
app.service('Configuration', [function() {
return {
getbaseUrl: function() { return "http://myrestservice.com/api/v1" },
getConfig: function() {
return {
answer: 42,
question: "??"
}
}
}
}]):
EDIT: example with an external fetch:
var app;
app = angular.module('my.module.config', []);
app.factory('ConfigurationData', ['$http', '$q', function(http, q) {
var deferredConfig = q.defer();
//error handling ommited
http.get('http://remote.local/config.json').success(function(data) {
return deferredConfig.resolve(data);
});
return {
getConfig: function() {
return deferredConfig.promise;
}
};
}]);
With this service, you can inject your config into other services, however, you can run into timing issues, as you have to inject and resolve the promise given by the service before anything you want to do with the config:
var app;
app = angular.module("my.other.module", ['my.module.config']);
app.factory('MyAwesomeService', ['ConfigurationData', function(config) {
config.getConfig().then(function(config) {
//do something with your config.
});
}]);
You get a bit more fine control here, as you can react to different inputs. Again, it depends on your use case. You can use a factory here if you need additional logic for structuring the configuration.
Lastly, if you want even more control over configuration, you can make a
Custom Provider
Providers can be pretty useful, but i think they are a bit harder to design. Considering a baseUrl from the configuration needed for your app to work, you could write a provider for the service needing the value of the baseUrl like this:
var app;
app = angular.module('my.angular.module', []);
app.provider("RestServiceProvider", function(){
this.baseUrl = 'http://restservice.com';
this.$get = function() {
var baseUrl = this.baseUrl;
return {
getBaseUrl: function() { return this.baseUrl; }
}
};
this.setBaseUrl = function(url) {
this.baseUrl = url;
};
});
This lets you do cool stuff in the config phase of your application:
app.config(['RestserviceProvider', function(restServiceProvider) {
restServiceProvider.setBaseUrl('http://wwww.myotherrestservice.com');
}]);
Every instance you fetch in a service/controller/etc. of RestService will now have the baseUrl set from the config phase from the moment you inject it.
For a more detailed overview, i suggest this gist.
Creating a stand-alone module that only has a service or a directive (or both) is a great way to make application-independent angular code. If you do this you can easily just take that .js file and plop it into any project, and all you need to do is inject it into your applications and it just works.
So doing something like:
angular.module('config', [])
.factory('config', function() {
return {
theme : 'nighttime',
cursor : 'sword',
...
};
});
Then you can just inject it into any application like so:
angular.module('myModule', ['config'])
.factory('myservice', function (config) {
var theme = config.theme;
var cursor = config.cursor;
// do stuff with night-time swords!
});
This is actually how the angular-ui team package all their directives, each directive is contained within its own module, which makes it easy for others to just take that code and reuse it in all their apps.

Resources