AngularJS Inject factory into another factory from the same module - angularjs

I'm trying to inject the factory Application into the ApplicationService factory. Both are defined in the same module.
Application factory (application.model.js)
(function(Object, coreModule) {
'use strict';
// the factory to expose that allows the creation of application instances
var ApplicationFactory = function() {
console.log("Application factory!");
return {foo: 'bar'};
}
coreModule.factory('Application', [ApplicationFactory]);
})(Object, angular.module('core'));
ApplicationService factory (application.service.js)
(function(coreModule) {
'use strict';
var ApplicationService = function(Application) {
var api = {
shout = function() {console.log(Application);}
};
return api;
}
ApplicationService.$inject = ['Application'];
coreModule.factory('ApplicationService', [ApplicationService]);
})(angular.module('core'));
Then I'm injecting ApplicationService factory into a controller and calling the method shout. I get undefined when in the console's log, Application is always undefined. If in a controller I innject Application it works. So i know both factories are working standalone.
Both files are being imported in my index.html.
I've spent hours looking for the issue but I can't find it. What am I doing wrong?

Please see working demo below.
You've got 2 options.
a) Remove square brackets here:
coreModule.factory('ApplicationService', ApplicationService)
b) Add injected Application as first element before ApplicationService:
coreModule.factory('ApplicationService', ['Application', ApplicationService])
var app = angular.module('core', []);
app.controller('firstCtrl', function($scope, ApplicationService) {
ApplicationService.shout();
});
(function(Object, coreModule) {
'use strict';
// the factory to expose that allows the creation of application instances
var ApplicationFactory = function() {
console.log("Application factory!");
return {
foo: 'bar'
};
};
coreModule.factory('Application', [ApplicationFactory]);
})(Object, angular.module('core'));
(function(coreModule) {
'use strict';
var ApplicationService = function(Application) {
var api = {
shout: function() {
console.log(Application);
}
};
return api;
};
ApplicationService.$inject = ['Application'];
coreModule.factory('ApplicationService', ApplicationService);
})(angular.module('core'));
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="core">
<div ng-controller="firstCtrl">
</div>
</body>

Related

How can i provide a .config function to configure my library

I have made a little library of code for angular js. I have created a .config method in my library's main module that depends on my moduleConfigProvider. I expect the consumer of my library to call .configure on my config provider during the app.config stage (asap on app start).
The problem is that my .config in my module seems to run BEFORE the app.config of the main app module. How can I work around this problem?
e.g. This is how i'm consuming the config. I need to consume it during the .config stage because I need to configure things like $httpProvider.
// this module provides initial configuration data for module
angular.module('mymodule')
.config(['$httpProvider', 'someOptionsProvider', 'myConfigProvider',
function ($httpProvider, someOptionsProvider, myConfigProvider) {
console.log("Consuming config now: ", myConfigProvider.config);
}])
Here is the config provider:
angular.module('mymodule.config')
.provider('myConfig', function() {
var _this = this;
_this.configure = configureMethod;
_this.config = {};
function configureMethod(configData) {
_this.config = configData;
console.log("Config set to:", configData);
};
this.$get = function() {
return _this;
};
});
And finally here is my app.config:
angular.module('app')
.config(['myConfigProvider', function(myConfigProvider) {
console.log("Running App config:", myConfigProvider);
var config = { a: 1 };
console.log("Config ready to send:", config);
myConfigProvider.configure(config);
}])
;
Okay, it is simple, just use other providers in your provider function as dependencies.
Check the following snippet
angular.module('mymodule', [])
.provider('myConfig', [
'$httpProvider',
function($httpProvider) {
var _this = this;
_this.configure = configureMethod;
_this.config = {};
function configureMethod(configData) {
//Do here anything with the $httpProvider
_this.config = configData;
console.log("Config set to:", configData);
console.log('Configuring $httpProvider')
};
this.$get = function() {
return _this;
};
}
])
angular.module('app', ['mymodule'])
.config(['myConfigProvider', function(myConfigProvider) {
console.log("Running App config:");
var config = {
a: 1
};
console.log("Config ready to send:", config);
myConfigProvider.configure(config);
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
</div>

how to inject factory into another factory in Angular

I have two modules and factories in both, and I need to implement factory from the first module into another module.
angular.module('APIs', [])
.value ("myValue" , "12345")
.factory('apiUrl',['config','url',apiUrl])
function apiUrl(config,url){
}
angular.module('users.service', ['APIs'])
.factory('userService',['myValue',userService])
function userService(apiUrl,myValue){
//login function
function login(){
console.log('myValue',myValue)
console.log('loginUrl',apiUrl)
}
return {
login:login
}
}
notice: no problem when I inject myValue, but the problem in APIs Factory
and my log:
Error: [$injector:unpr] http://errors.angularjs.org/1.5.0/$injector/unpr?p0=urlProvider%20%3C-%20url%20%3C-%20apiUrl%20%3C-%20userService
at Error (native)
and sorry for my English.
I would do it like this:
If you create factory use angular.module('app').factory(). If you create service use angular.module('app').service()
Always try to have same module name. It is easier later, when you have big application, because of dependency injection.
Try to keep files separately, and concatenate it later, for example using gulp gulp-concat
Try to keep all you configuration in app.js file and, when you concatenating file, remember, this file should be on top.
I would keep values and constants in app.js file or would create new file like factory or service and include it, same as I injected it below.
app.js
(function () {
'use strict';
var app = angular.module('app', [
// other module
]);
app.value('myValue', '12345');
app.constant('myConst', 'some_constant');
app.config(['$interpolateProvider', function ($interpolateProvider) {
$interpolateProvider.startSymbol('[[');
$interpolateProvider.endSymbol(']]');
}]);
}());
factory.js
(function () {
'use strict';
angular
.module('app')
.factory('apiUrlFactory', apiUrlFactory);
apiUrlFactory.$inject = [];
function apiUrlFactory() {
var self = this;
self.url = 'some_url';
return self;
}
}());
service.js
(function () {
'use strict';
angular
.module('app')
.service('userService', userService);
userService.$inject = ['apiUrlFactory', 'myValue'];
function userService(apiUrlFactory, myValue) {
var self = this;
self.login = function () {
console.log('myValue', myValue);
console.log('loginUrl', apiUrlFactory.url);
};
return self;
}
}());
If you have more questions, do not hesitate to contact with me. Also try angular style guide https://github.com/johnpapa/angular-styleguide It will help you a lot.

TypeScript Controller not handling HTTP promises

I have been learning Angular and everything's been going smoothly. I have decided to try and incorporate TypeScript into this and wrote a small test controller in an already existing Angular/WebApi project I have been working on.
The controller "works" and initializes just fine, however, my $scope properties are not being updated when set to an HTTP promise. I have attached a "working" example of my issue using the TypeScript generated JS file. When debugging, I can see the then get triggered on the promise and the data I expected does return, but the page displays {}
Here is my actual TypeScript file.
/// <reference path="../../tds/angularjs/angular.d.ts" />
module RecordEditor {
export interface Scope extends ng.IScope{
tableId: any;
}
export class Controller {
$scope: Scope;
api : any;
constructor($scope: Scope, myApi: any) {
this.api = myApi;
this.$scope = $scope;
this.$scope.tableId = this.api.getTestResponse();
}
}
}
var app = angular.module("myApp");
app.controller("RecordEditor.Controller", ['$scope', 'myApi', RecordEditor.Controller]);
That controller is the only thing I have actually written in TypeScript. All the other controllers are in JavaScript and the same api I built returns responses just fine with those.
Below is the actual runnable snippet code with the JavaScript version of my Controller.
(function() {
var app = angular.module('myApp', []);
}());
(function() {
var myApi = function($http) {
var getTestResponse = function() {
// Hope it is okay to use SE API to test this question. Sorry if not.
return $http.get("https://api.stackexchange.com/2.2/sites")
.then(function(response) {
return "Hello!";
});
};
return {
getTestResponse: getTestResponse,
};
};
var module = angular.module("myApp");
module.service("myApi", ['$http', myApi]);
}());
var RecordEditor;
(function(RecordEditor) {
var Controller = (function() {
function Controller($scope, myApi) {
var _this = this;
this.api = myApi;
this.$scope = $scope;
this.$scope.response = this.api.getTestResponse();
this.$scope.ctorTest = 42;
}
return Controller;
})();
RecordEditor.Controller = Controller;
})(RecordEditor || (RecordEditor = {}));
var app = angular.module("myApp");
app.controller("RecordEditor.Controller", ['$scope', 'myApi', RecordEditor.Controller]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.min.js"></script>
<div ng-app="myApp" ng-controller="RecordEditor.Controller">
<div >
Scope property set in constructor: {{ctorTest}}
</div>
<div >
Scope response value: {{response}}
</div>
<div >
Scope response should have been "Hello!"
</div>
</div>
Can anyone actually tell me what I am doing wrong? Everything looks fine to me.
var getTestResponse = function() {
return $http.get("https://api.stackexchange.com/2.2/sites")
.then(function(response) {
return "Hello!"; // <-- does not do what you think it does
});
};
/** elsewhere **/
this.$scope.response = this.api.getTestResponse();
The inner return statement here does not return a value from getTestResponse. Instead, it returns a value from the Promise which is basically discarded. getTestResponse returns immediately with a Promise object that is of no particular use for binding to the scope.
Fixed version of the JS:
(function() {
var app = angular.module('myApp', []);
}());
(function() {
var myApi = function($http) {
var getTestResponse = function() {
// Hope it is okay to use SE API to test this question. Sorry if not.
return $http.get("https://api.stackexchange.com/2.2/sites")
.then(function(response) {
return "Hello!";
});
};
return {
getTestResponse: getTestResponse,
};
};
var module = angular.module("myApp");
module.service("myApi", ['$http', myApi]);
}());
var RecordEditor;
(function(RecordEditor) {
var Controller = (function() {
function Controller($scope, myApi) {
var _this = this;
this.api = myApi;
this.$scope = $scope;
/** FIXED **/
this.api.getTestResponse().then(function(v) { _this.$scope.response = v; });
this.$scope.ctorTest = 42;
}
return Controller;
})();
RecordEditor.Controller = Controller;
})(RecordEditor || (RecordEditor = {}));
var app = angular.module("myApp");
app.controller("RecordEditor.Controller", ['$scope', 'myApi', RecordEditor.Controller]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.min.js"></script>
<div ng-app="myApp" ng-controller="RecordEditor.Controller">
<div >
Scope property set in constructor: {{ctorTest}}
</div>
<div >
Scope response value: {{response}}
</div>
<div >
Scope response should have been "Hello!"
</div>
</div>
Ok here's the issue. You are trying to set your response to the actual callback function.
Instead, you have to set the response property inside callback using the response you got from the http call.
Here is the api function
var getTestResponse = function() {
return $http.get("http://vimeo.com/api/oembed.json?url=http%3A//vimeo.com/76979871");
};
Here is your controller code where you have to set your response property to bind to UI.
_this.api.getTestResponse().success(function(resp) {
_this.$scope.response = resp.height; //I just used height property from response as example
});
Here is the jsfiddle
http://jsfiddle.net/HB7LU/7386/
Make sure you first get your stackexachange call working. I used vimeo call as example.
Let me know if you have any questions.
So, in your TypeScript code, you have to change
this.$scope.tableId = this.api.getTestResponse();
to
this.api.getTestResponse().then((resp) =>
{
this.$scope.tableId = resp;
});
And make your API just return a promise.

Issues wiring up a new Angular controller module

I wonder if someone could assist me in figuring out how to wire up my new angular service module.
I keep getting the same Javascript error :
Error: [$injector] Unknown provider: gridHierarchyServiceProvider" <-- gridHierarchyService
My new services/gridHierarchyService.js file :
(function () {
'use strict';
var controllerId = 'gridHierarchyService';
angular.module('app').controller(controllerId, ['common', gridHierarchyService]);
function gridHierarchyService(common) {
var service = {
getDataSourceSchema: getDataSourceSchema
};
return service;
function getDataSourceSchema() {
var i = 1;
// TESTING...
}
}
});
and in my dashboard.js file, I attempt to inject this new service module:
(function () {
'use strict';
var controllerId = 'dashboard';
angular.module('app').controller(controllerId, ['common', 'datacontext', 'gridHierarchyService', dashboard]);
function dashboard(common, datacontext, gridHierarchyService) {
...
}
and of course I'm loading it up in my index.html:
<!-- app Services -->
<script src="app/services/datacontext.js"></script>
<script src="app/services/gridHierarchyService.js"></script>
<script src="app/services/directives.js"></script>
However, I'm clearing missing something here.
I also tried mimicking my datacontext.js service, using the .factory() call:
angular.module('app').factory(serviceI,d [...]);
but it doesn't work.
========== UPDATE !!! ============
I'm happy to say it was a very easy fix, and thanks to the community here !
WORKING SERVICE :
(function () {
'use strict';
var serviceId = 'gridHierarchyService';
angular.module('app').factory(serviceId, ['common', gridHierarchyService]);
function gridHierarchyService(common) {
var service = {
getDataSourceSchema: getDataSourceSchema
};
return service;
function getDataSourceSchema() {
var i = 1;
i = 2;
}
}
})();
I see that you are defining your controllers inside anonymous functions but that you never execute those anonymous functions.
Your code:
(function(){
//declarations
alert('You will never see me because I do not execute');
});
Fixed code (notice the parens at the end):
(function(){
//declarations
alert('You can see me!');
})();
See the above code run here: http://jsfiddle.net/wilsonjonash/cDBc7/
See more about the module pattern here:
http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html
Also, you were right to try factory for a service. To make your gridHierarchyService into a service (rather than a controller), just change controller to factory or service in
var controllerId = 'gridHierarchyService';
angular.module('app').controller(controllerId, ['common', gridHierarchyService]);
Hope that does the trick for you.

AngularJS use custom services in custom providers

I have a simple question about the dependency injection in Angular. I create custom services in order to use them within each other. Unfortunately I receive errors the way I was trying it. This is my Code:
var myApp = angular.module('app', []);
myApp.service('$service1', ['$rootScope', function($rootScope) {
this.test = function() {
console.log('service1');
};
}]);
myApp.provider('$service2', ['$service1', function($service1) {
var service = 'service2';
this.registerService = function(mytext) {
service = mytext;
};
this.$get = function() {
var that = {};
that.test = function() {
console.log(service);
};
return that;
};
}]);
myApp.config(['$service2Provider', function($service2Provider) {
$service2Provider.registerService('changed service2');
}]);
myApp.controller('AppCtrl', ['$rootScope', '$service1', '$service2',
function($rootScope, $service1, $service2) {
$service1.test();
$service2.test();
}]);
Error: [$injector:modulerr] Failed to instantiate module app due to:
[$injector:unpr] Unknown provider: $service1
http://errors.angularjs.org/1.2.0-rc.2/$injector/unpr?p0=%24service1
If you remove the dependency of $servic1 in $service2 it will work, but why?
The code is mostly right, except you have to inject service dependencies in $get, not in the provider constructor function, like this:
myApp.provider('$service2', function() {
var service = 'service2';
this.registerService = function(mytext) {
service = mytext;
};
this.$get = ['$service1', function($service1) {
var that = {};
that.test = function() {
console.log(service);
};
return that;
}];
});
It appears that provider can not inject such a dependency. If you rewrite $service2 using a factory, it works:
myApp.factory('$service2', ['$service1', function($service1) {
var that = {};
that.test = function() {
$service1.test();
console.log('service2');
};
return that;
}]);
See this plunker: http://plnkr.co/edit/JXViJq?p=preview
Also I believe that service names starting with a $ a reserved for AngularJS and its extensions. Use names without the $ at the beginning for services defined by your application.

Resources