If I have code similar to this question on injecting another controller to a directive:
angular.module('paramApp', []);
angular.module('paramApp').controller('ParamCtrl', ['$scope', '$http', function($scope, $http) {
.
.
.
}]);
angular.module('deviceApp', ['paramApp']);
angular.module('deviceApp').directive('DeviceDirective', function () {
return {
.
.
.
controller: 'ParamCtrl'
};
});
When I minify js, the injected dependencies of $scope and $http break, how can I explicitly define the dependencies of ParamCtrl when creating DeviceDirective to prevent uncaught injector issues with bundled js?
I am very late to this question but I'll give it a shot.
The syntax is based on John Papa's Angular style guide
First you need a way to make your controller reusable. Convert it from an anonymous function to a named function and pass it to your angular app like so:
// Named controller function
ParamCtrl function($scope, $http) {
this.doStuff
}
// Bind it to your app
angular.module('paramApp').controller('ParamCtrl', ['$scope', '$http', ParamCtrl );
// While we are at it, do the same with your directive
DeviceDirective function (controlerParam) {
return {
...
controller: controlerParam
}
}
// Bind it to your app
angular.module('deviceApp', ['ParamCtrl', DeviceDirective]);
However, if you meant to pass the controller's scope to your directive refer to fiznool's post
Related
I have a PhoneGap App with AngularJs 1.5.5, OnsenUI 2 and EmojiOne.
I am trying to access the emojione variable inside of the angular controller:
ons.bootstrap.controller('AppController', ['$scope', '$timeout','$http', '$sce', function ($scope, $timeout, $http, $sce) {
emojione.imageType = 'svg';
emojione.sprites = true;
emojione.imagePathSVGSprites = '../res/sprites/emojione.sprites.svg';
...
I have some function calls later on as well.
It is working as intended when i run it on my PC, but fails to resolve "emojione" (it is undefined) on android.
This is my first time working with angularjs and JavaScript so it may be something really simple.
Are you loading emojione library from a cdn?
Mobile has internet access?
When dealing with angularjs and standard javascript libraries, I like to make a module and factory simply for accessing the root variable, just like you are trying to do:
angular.module('emojioneModule', [])
.factory('emojione', function($window) {
return $window.emojione;
});
This allows you to inject the reference, and allows you to mock up the emojione for unit tests, as you can inject a mock instead.
ons.bootstrap.controller('AppController', ['$scope', '$timeout','$http', '$sce', 'emojione', function ($scope, $timeout, $http, $sce, emojione) {
emojione.imageType = 'svg';
emojione.sprites = true;
emojione.imagePathSVGSprites = '../res/sprites/emojione.sprites.svg';
...
However, you could just inject $window, and access it directly from there.
I have the following code:
main.js
angular.controller('myCtrl', function($scope, $rootScope) {
$scope.name = "Bob";
}
myservices.js
angular.factory('myService', function($http) {
var myService = {
async: function(params) {
// $http returns a promise, which has a then function, which also returns a promise
var promise = $http.get("http://myws/user/info/"+params).then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
return response.data;
});
// Return the promise to the controller
return promise;
}
};
return myService;
});
How can inject myService in myCtrl ? considering they are in two separated files.
We need to add in order all of our scripts we have created to run this angular, take note the order:
<script src="angular.js"></script>
<script src="main.js"></script>
<script src="myservices.js"></script>
main.js should look like:
var app = angular.module("MyModule", []);
app.controller('myCtrl', function($scope, $rootScope, myService) { /* implementation */})
services.js should look like:
app.factory('myService', function($http) { /* implementation */});
So in our main.js we are creating a module to attach all of our services, factories, providers, values, constants, controllers and directives. It also allows us to put the config and run phase functions in.
The module is instantiated via:
angular.module("MyModule", []);
We're providing a second argument of other dependant modules
If we needed to, we could ask angular for the module again, in the case of use javascript modules:
var app = angular.module("MyModule");
Below are several thing you need to do.
Should be they should belong same/different angular module(if its different module then you have inject into main module to use it).
You need to use angular.module('myApp') to bind components to it, so that the service will be available in that module.
Code
//app.js
angular.module('myApp', ['myApp.service']); //this should be module definition somewhere
//service.js
angular.module('myApp.service', [])
angular.module('myApp.service').factory('myService', function($http) {
//service code
});
//controller.js
angular.module('myApp').controller('myCtrl', function($scope, $rootScope, myService) {
console.log(myService); //service instance here
$scope.name = "Bob";
}
you can inject service in your controller
like:
main.js:
angular.module('myApp', []).controller('myController', ['$scope', 'myService',
function ($scope, myService) {
}
]);
myService.js:
angular.module('myApp').factory('myService', function($http) {
//service code
});
for different file but same module then ensure that file is loaded before use.
Make sure the files are both actually loaded. How to do that is up to you, perhaps you're using some implementation of require(), or you simply list all the files in your HTML as <script> tags.
Clarify what module structure you want to have. Should both be part of the same module, or should they be separate modules?
Same module: One file needs to declare the module, the other needs to extend it:
angular.module('Foo', []) // declares new module
.controller(..)
angular.module('Foo') // extends existing module
.factory(..)
Different modules:
angular.module('Foo', []) // declares new module
.factory(..)
angular.module('Bar', ['Foo']) // declares new module
.controller(..) // and imports other module
Inject into the controller:
.controller('myCtrl', function ($scope, myService) ..
I'm using Jasmine for testing my AngularJS application. I have an Authenticaiton controller, which calls a function which I define in the scope from the Application controller. So:
1. AppController
$scope.setUser = function() {}
2. AuthenticationController
$scope.setUser(User);
I am testing the AuthenticationController, and setUser() is not inside the scope of AuthenticationController. How do I inject the scope/function from the AppController?
The error message:
TypeError: $scope.setUser is not a function
Should I mock the whole function? Is the structure smelly? What's the best way to do this?
EDIT:
In the real app, AuthenticationController gets injected into my dashboard-app.
AuthenticationController:
angular
.module( 'authentication', [])
.controller('AuthenticationController', AuthenticationController);
AuthenticationController.$inject = ['$scope', '$rootScope', 'AUTH_EVENTS', 'AuthenticationService'];
Dashboard:
angular
.module('dashboard', [
'authentication'
])
.run(run);
Info: Names are changed in my question to make it easier to understand.
inject $rootScope into your controllers.
AppController :
$rootScope.setUser = function() {}
AuthenticationController
$rootScope.setUser();
I wonder why I can't access a factory within the same module.
As I think it is better to build a web app with different independent modules, I would like to group all methods (services, factories, directives, ...) within the same module.
What do I do wrong?
app = angular.module("MyGreatModuleProvider", []);
app.factory("MyFactory", function($rootScope, $scope) {
return {
myFunction: function() {
console.log("Hello World");
}
}
});
app.controller("myCtrl", function($scope, MyFactory) {
MyFactory.myFunction();
// This doesnt't work, unknown provider
});
Factories don't have a $scope
If you remove the $scope and only keep the $rootScope it works just fine
You can remove both $scope and $rootScope from the factory declaration. Here's a plunker.
Define your injected object names to let the Angular know what to inject into fields:
app.controller("myCtrl", ['$scope', 'MyFactory', function($scope, MyFactory) {
MyFactory.myFunction();
}]);
It's a good practice especially if you are going to compile your application.
Moreover as others pointed out: factories doesn't have $rootScope and $scope.
I have a model called 'user', 'user' has a controller called 'login' and a directive called 'userMenu', what I'm trying to achieve is that the userMenu directive uses the controller 'login' that's available in the module. Maybe I don't understand well how the modules and directives should work but I'm doing the following:
First, I define my controller like this:
angular.module('user', []).
controller('login', ['$scope', '$http', function($scope, $http){
$scope.logIn = function(){
//Do something...
}
}
Then, in my directive...
angular.module('user', []).
directive('userMenu', function(){
return {
priority: 0,
templateUrl: 'app/includes/user/menu.html',
replace: true,
restrict: 'A',
controller: 'login',
}
});
But the I get this:
Error: Argument 'login' is not a function, got undefined
Would you please guide me on the use of directives and controllers within modules?
The problem is that you are re-defining the user directive while preparing your directive. I presume that you wanted to register both a controller and a directive on the same module. If so you can register your directive like this:
angular.module('user').directive('userMenu', function(){
return {
...
}
});
Notice that there is no second argument ([]) to the call of angular.module which means that you want to retrieve an instance of already defined module instead of defining a new one.