Angular 1 - Get the module a controller is running in - angularjs

I am working inside a platform where you can create controllers using a web form and write angular code inside of them... but I do not have access to the parent module.
So here I am in my module, trying to apply a filter but I cannot apply a filter if I do not know the module.
Is there any way I can find out what module I am running in from a controller?
I only have access to this code:
function ($scope, spUtil, snRecordWatcher, $rootScope) {
}
I cannot see the angular.module(blabla)
Thank you,
Alexandru S.

If you inject $rootElement you can use it to find the name of the module under which the current controller is running. e.g.:
function ($scope, spUtil, snRecordWatcher, $rootScope, $rootElement) {
var module = $rootElement.attr('ng-app');
}

Related

registerModule with dependencies

I'm building an app with MEAN.JS and I'm trying to use a controller from another module. I've found that I can do this with dependency injection:
angular.module(‘MyModule’, [‘Dependency’]);
But the way modules are created in MEAN.JS is:
ApplicationConfiguration.registerModule('MyModule');
And I can't just pass a second parameter to registerModule. So, how should I do this? Do I have to use both methods? Am I doing it wrong?
Example
I want to add a new model: Campaign. Campaigns are created by admins only, but can be seen by the "campaign owner" (another User). The create campaign form should list available Users, so the admin can select the one that's going to be the "owner" of that Campaign.
The problem is, the create campaign form is controlled by CampaignsController, how can I list Users? I've used another controller (UsersController) and thats the problem, it is undefined because we are in the Campaign module.
EDIT:
The problem was grunt autorestarting the app incorrectly:
I moved the controller from one module (folder) to another, but grunt was still trying to load it from the old path, and thus failing: Controller not found. I thought the problem was dependency injection, but you only have to close grunt (Ctrl+C) and run it again. Problem solved.
Anyways, thanks for the answer #gilBirman cause it is correct: there is no need to inject anything with MEANJS.
MEAN.js makes all the modules registered via registerModule available to all other modules in your app by adding it as a dependency to the main app called mean. Here's the part of the MEAN.js source code that does this:
var applicationModuleName = 'mean';
....
// Add a new vertical module
var registerModule = function(moduleName) {
// Create angular module
angular.module(moduleName, []);
// Add the module to the AngularJS configuration file
angular.module(applicationModuleName).requires.push(moduleName);
};
So you're on the right track, however it sounds like you are trying to inject a controller. However, in angular, controllers are not injectable. You can inject services, factories, values, and constants.
First create your own module for example:
angular.module('app.controllers', []) - angular module with controllers.
then add controller to that module:
angular.module('app.controllers', [])
.controller('dashboard.admin.account.controller', ['$scope', ($scope) { .... }]);
then create global module which will bind to your markup:
angular.module('app', [
'app.controllers'
'ui.router',
'ngAnimate'
]);
then bootstrap your global module to markup:
domReady(function () {
angular.bootstrap(document, ['app']);
});
Now you can use your controller.

AngularJS: unknown provider until after page loads?

So this is really weird, maybe it has a simple answer I'm missing. The following code gives an unknown provider error:
var foo = angular.module('foo', [ 'ngRoute', 'ngAnimate', 'ngCookies' ]);
foo.factory('fooApi', function ($scope, $http) {
var url = '/api/';
var factory = {};
factory.action = function (fields) {
fields.userid = $scope.userid;
fields.token = $scope.token;
console.log(JSON.stringify(fields));
return $http.post(url, { data: fields });
};
return factory;
})
.controller('loginController', function ($scope, fooApi) {
// do stuff
});
It's all loading together in the same file, and I'd think the factory being first would resolve and the injector would be able to find it when referenced below. But it gives an unknown provider error.
However, if I comment out the controller and wait for the page to load and then do the exact same controller declaration in the Chrome JS console it works fine.
Anyone run into this before and know how to deal with it? I haven't been able to find this same exact issue anywhere.
Like #tasseKATT said, you can not inject $scope into a service, particularly a factory. Maybe your confusion is because $scope can be injected in controllers, so you tried to injected into a factory.
An interesting thing is that the $scope that you see being injected into controllers is not a service - like the rest of the injectable stuff -, but is a Scope object.
The main purpose of $scope is a king of glue between views and controllers, it doesn't make much sense to pass a $scope into a service.
The services only have access to the $rootScope service.
If you need to pass the $scope of a specific controller to a service always you can pass it like parameter of a function in the service. This approach is not recommended because starting to break the SoC and the single responsibility principle, but maybe could fit you.
Good luck :-)

AngularJS: how to "create" controller in unit test, and why scope is not defined?

everywhere in application my company created we used this example of how to create a controller :
app.myFunnyController = function($scope.....){}
but i see that everywhere in test people are using this way of creating controllers:
app.controller('myFunnyController', function ($scope) {
}
And i can see that when i am creating my test and using app.myFunnyController declaration:
'use strict';
describe('publicCtrl', function(){
beforeEach(module('app'));
it("should be true", inject(function($controller){
var scope = {},
ctrl = $controller('myFunnyController', {$scope : scope});
expect(scope.data).toBe("test2");
}));
})
I getting an error of myFunnyController is not a function. If i using the second type of declaration, everything works fine. Why does this happend?
An other problem is that i am getting error: scope is not defined.
I am new to Karma and Unit testing for front end, what am i doing wrong?
From my understanding, the second syntax (app.controller(...)) registers the controller function on the module. The first syntax just adds the controller function as an attribute of the module. app.controller does a bit more magic under the hood so that when you call $controller('myFunnyController, ...) in your test, the module knows about the controller and can run it. This is the recommended way to define controllers according to the angular controllers guide.

Angular - Decorating Directives

I'm trying to use Angular's "decorator" capability to add functionality to some directives. Assume that my directive's name is myDirective. My code looks like this:
angular.module('app').config([
'$provide', function($provide) {
return $provide.decorator('myDirective', [
'$delegate', '$log', function($delegate, $log) {
// TODO - It worked! Do something to modify the behavior
$log.info("In decorator");
}
]);
}
]);
I keep getting this message:
Uncaught Error: [$injector:unpr] Unknown provider: myDirectiveProvider from app
To the best of my ability, the directives are already registered by the time the decorator function runs. Any insight would be appreciated!
This article shows how you can, in fact, use decorator() with directives.
You just have to include "Directive" as the suffix for the name. Hence, in my example I should have been doing
return $provide.decorator('myDirectiveDirective', ['$delegate', '$log', function($delegate, $log) {
// TODO - It worked! Do something to modify the behavior
$log.info("In decorator");
// Article uses index 0 but I found that index 0 was "window" and index 1 was the directive
var directive = $delegate[1];
}
http://angular-tips.com/blog/2013/09/experiment-decorating-directives/
Decorators as created with the decorator method are for services only. They have to be created with service, factory, provider or value. See the docs here.
If you want to decorate a directive, you can make another directive with the same name. Both directives will be used when the DOM is compiled, and you can define the compilation order using priority.
Alternatively, if you are able to modify the code that uses the directive you are trying to decorate, then you can just make a new directive that uses the original in its template.

angularjs - runtime dependency injection?

Simple one I hope..
Here's a plunker for reference.
I know how to specify a dependency at compile-time (see MainCtrlInjected controller). But how do I pull down a dependency at runtime, giving the name of that dependency? (see MainCtrlInjectedRuntime controller)
You can use $injector to get your value at runtime:
Check my forked plunker: http://plnkr.co/edit/iVblEU?p=preview
Code:
app.controller('MainCtrlInjectedRuntime', [
'$scope',
'$injector'
($scope, $injector) ->
nameValHandle = 'nameVal'
# !!! This is how you inject at runtime
name = $injector.get(nameValHandle)
$scope.name = name
])
I am just getting into angularjs, but I believe the appropriate way to handle this situation would be to inject a service into MainCtrlInjectedRuntime. The injected service would have your somehowGetNameFromValue method.

Resources