I'm trying to make an Angular Service that houses common functions.
I bundled the code within my MVC app:
bundles.Add(new ScriptBundle("~/bundles/Angular")
.IncludeDirectory("~/app", "*.js", true));
And I checked in Developer Tools if it actually brought in my Common Folder with Common.js :
I added Common to the App :
var app = angular.module('app',
[
'JobCtrl',
'JobSvc',
'WebsiteCtrl',
'WebsiteSvc',
'myClientCtrl',
'ClientSvc',
'MediaCompanyCtrl',
'MediaCompanySvc',
'PageAlertSvc',
'ui.bootstrap',
'ui.bootstrap.tpls',
'Common'
]
);
and to the Controller:
angular.module('app', ['ui.bootstrap', 'ui.bootstrap.tpls'])
.controller('JobCtrl',
[
'JobService',
'WebsiteService',
'MediaCompanyService',
'ProductService',
'$scope',
'$uibModal',
'PageAlertService',
'Common',
function (JobService, WebsiteService, MediaCompanyService,
ProductService, $scope, $uibModal,PageAlertService, Common)
This is what my Common.js file looks like:
angular.module('app')
.service('Common', function () {
this.heyThere = function ()
{
console.log('Just wanted to say hey there')
};
});
Whenever it is called within my JobCtrl I get a Error: $injector:unpr
Unknown Provider.
Could anyone see what I may be doing wrong where it won't recognize my Common.js file? When I move Common.js to the Services folder and try calling it within my controller it works, but not when it is in my Common Folder. Makes no sense!
Thanks in advance!
That is simply because you are defining your app..twice!!!!
angular.module('app', []) // this is where you re-define your app
.service('Common', function () {
this.heyThere = function ()
{
console.log('Just wanted to say hey there')
};
});
should be:
angular.module('app')
.service('Common', function () {
this.heyThere = function ()
{
console.log('Just wanted to say hey there')
};
});
the module function has 2 modes.. with 2 arguments you are setting up your app.. with a single argument you just getting a reference to an existing app (which is already defined before that)
Please be careful when you use the declaration of a module. You are basically reassigning the app module to different instances.
angular.module('app', [dependencies]) //Constructs a module with dependencies
angular.module('app').service(...) //Associates the components (service)
//with the app module.
Related
I am creating small application called puzometr. It is for educational needs only. I want to create this application using AngularJS. Also, I want to use RequireJS as module system.
I have strange problem. I created my test controller and I got problem: controller initialization fires two times.
Firstly, full code available here on GitHub (wait, don't click me, I will explain everything below).
So, problem is in myCtrl.js file. Here is code of this file:
define(['angular'], function (angular) {
var module = angular.module('main.myModule', []);
module.controller('main.myCtrl', function ($scope) {
console.log($scope.$id);
$scope.bob = function () {
}
})
});
It is included in main/controllers/controllers.js by this:
define(['app', 'main/controllers/myCtrl'], function (app) {
var module = angular.module('main.controllers', ['main.myModule']);
});
This file included in main.js by this code:
angular.module('main', ['ngRoute', 'main.services', 'main.controllers', 'main.directives']);
And main.js is included into app.js:
var app = angular.module('myApp', ['ngRoute', 'main', 'common']);
So, I incidentally noticed, that function definition in myCtrl controller fired two times. I put console.log there and saw this:
Can you please explain me why is this happens? Why controller is being initialised two times?
Also, I have this in ng-inspector:
So one scope is created as child for another scope. Notice, that scope with id 3 has correct controller name.
If you use ng-route to register controllers and bind them with views, then don't add them again using attributes in your html files.
I am a bit newbiew with javascript and i am starting to use angular.js
So my question is if there is a way to inject a controller inside a module that is declared in an anonymous function
my code looks like this
app.js
(function(angular) {
var app = angular.module('Organizer', ['ngMaterial', 'ngAnimate', 'ngAria']);
})(angular);
siteController.js
(function(angular, app) {
app.controller('site', function($scope, $mdDialog)
{
var alert = $mdDialog.alert({
title: 'Test',
content: 'Testing',
ok: 'Exit'
});
$mdDialog.show(alert);
});
})(angular);
i have tried to look for ways if it is possible, but still i would like to see if anyone here could explain how this can be made if it could.
Note: I have already used angular.js before and i wanted to try a different way to declare controllers so the client wont have any way to modify it
If you create a module in Angular, then you can not obfuscate it in this way. In the console, a user can just run angular.module('Organizer') to get access to your app, and then call any method they want on it.
The reason your code won't work as written, is because you are not passing the app variable to your anonymous function. So if you want to add a controller to the Organizer module, then you would do something like this:
(function(angular)
{
angular.
module('Organizer').
controller('site', function($scope, $mdDialog)
{
...
});
})(angular);
Theres no need to wrap any of this code in self executing functions as if you are trying to keep variables out of the global scope. The only one that's global is the "angular" object.
Your app.js should only have
'use strict';
angular.module('Organizer', ['ngMaterial', 'ngAnimate', 'ngAria']);
You controller file should only have
'use strict';
angular.module('Organizer').controller('siteController', function($scope, $mdDialog) {
var alert = $mdDialog.alert({
title: 'Test',
content: 'Testing',
ok: 'Exit'
});
$mdDialog.show(alert);
});
The first call to module in app.js passes the second parameter which angular uses to instantiate your module. Subsequent calls that omit the second parameter "get" the module.
In my Angular application I adding tracing functionality, which should work as separate plugin, so if script included into HTML Angular should create service and initialize (run) it. Plugin is service because it has mandatory dependency on $rootScope.
For implementation I select to use Angular factory, like (code is in myservice.js):
angular.module('app').factory('mysevice', ['$rootScope', '$interval', serviceFunc]);
function serviceFunc($rootScope, $interval) {
return {
run: function () { ... }
}
}
And now I have problem how to immediately initialize it. My solution is to enhance Angular app run function (code is in myservice.js):
window.app.run(['mysevice', function (srvc) {
srvc.run();
}]);
Where app defined in separate main app.js file like:
var app = window.app = angular.module('app', [...]);
app.run(['$state', 'breeze', ...,
function ($state, breeze, ...) { ..real initialization.. }
The code is working fine. Both main run and run for myservice calls are fine. The application together with the service are working well, but the code looks ugly, especially storing the app in the global window object and multicasting the run function.
Is there a better way to do Angular service and initialize it immediately after app starts with some other Angular services dependencies.
You can call angular.module('app').run(function(){...}). So you will not need a global variable anymore.
Example:
angular.module('app').run(['mysevice', srvc.run.bind(srvc)]);
I'm trying to get into the habit of structuring my Angular projects following LIFT protocol (Locate, Identify, Flat, Try(Dry)) but I'm having some difficulty resolving dependencies from other files.
I have the following factory:
(function () {
'use strict';
angular
.module('CBPWidget', [])
.factory('apiManufacturers', apiManufacturers);
function apiManufacturers () {
function hello () {
return 'hello';
}
return {
hello: hello
};
}
})();
and the following controller:
(function () {
'use strict';
angular
.module('CBPWidget', [])
.controller('stepOneController', stepOneController);
stepOneController.$inject = ['$scope', 'apiManufacturers'];
function stepOneController ($scope, apiManufacturers) {
$scope.step = 'step1';
console.log(apiManufacturers.hello);
}
})();
and the following error is thrown:
Error: [$injector:unpr] Unknown provider: apiManufacturersProvider <- apiManufacturers <- stepOneController
My factory JS file is placed above the controller JS file in my HTML (which will be minified).
Any advice on where I'm going wrong would be greatly appreciated as I'm new to structuring projects this way.
Here you are creating CBPWidget module two times.
angular.module('CBPWidget',[]) is used for creating module and
angular.module('CBPWidget') is used for getting already created module.
so replace controller code with this :
(function () {
'use strict';
angular
.module('CBPWidget')//now you are getting CBPWidget module
.controller('stepOneController', stepOneController);
stepOneController.$inject = ['$scope', 'apiManufacturers'];
function stepOneController ($scope, apiManufacturers) {
$scope.step = 'step1';
console.log(apiManufacturers.hello);
}
})();
Your angular.module('CBPWidget', []) block code is redefining angular app, which was flushing apiManufacturers service associated with it, & it is defining controller in it. You should never do that, you should use existing module which was already defined.
Code
angular
.module('CBPWidget') //don't overide app here use existing
.controller('stepOneController', stepOneController);
From the documentation for AngularJS, you'll find that
.module('CBPWidget', [])
is different from
.module('CBPWidget')
The latter is what you need to refer to a module, the former is for defining one. In all cases except where you first define it, you should be using the latter form.
I'm using the following angularjs project structure:
index.html
js/
-- angularjs
-- application.js
-- shared
-----SharedModule.js
-----LocalizeService.js
-----OtherSharedService.js
-- user
-----UserModule.js
-----LoginController.js
-----RegisterController.js
-----UserService.js
In other words I group files not by their type (e.g. services/controllers/directives), but by their logic purpose (e.g. user/shared/cart etc). I read this is the correct approach for large projects.
The main application.js file includes the modules like this:
angular.module('myApplication', [
'ngRoute',
'ngCookies',
'sharedModule',
'userModule',
'dahsboardModule',
])
Then, each module includes the related controllers/directives/services/whatever.
e.g. SharedModule.js
var sharedModule = angular.module('sharedModule',[]);
sharedModule.factory('Localize', ['$http', '$rootScope', '$window', LocalizeService]);
sharedModule.controller('someController',['$rootScope',SomeController]);
Then I implement the logic in each separate file.
My question is: what design pattern should I use to implement the logic of each separate service/controller?
I read this book: http://www.addyosmani.com/resources/essentialjsdesignpatterns/book/
and so far my beloved design pattern is 'Revealing module pattern' which is kinda omni-purpose design pattern. I used it many times in other projects (w/o angularjs).
But it seems I cannot use it with angularjs.
var LocalizeService = (function() {
})();
How can I pass all the stuff like $rootScope/$http to the module?
This is how it works for me now:
function LocalizeService($http,$rootScope,$window) {
var localize = (function() {
function publicFunction() {
// do smth.
}
return {
someFunction: publicFunction
}
})();
return localize;
}
But I'm not sure if it is quite correct. Could you please kindly advise?
You an use a service with a constructor instead of a factory:
var LocalizeService = (function() {
function LocalizeService($http, $rootScope, $window) {
}
LocalizeService.prototype = {
publicFunction: function() {
}
};
LocalizeService.$inject = ['$http','$rootScope','$window'];
return LocalizeService;
}());
sharedModule.service('Localize', LocalizeService);