Angular depandency problems at minify compiling - angularjs

I have an app which uses a lot of different js files. When I compile the app normaly with gulp everything works well, but when I compile everything in one file to minify it, I get an error (Uncaught Error: [$injector:modulerr]).
app-55bb2aca73.js:4 Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.5.8/$injector/modulerr?p0=app&p1=Error%3A%20%…http%3A%2F%2Flocalhost%3A8080%2Fbuild%2Fjs%2Fapp-55bb2aca73.js%3A4%3A30075)
at app-55bb2aca73.js:4
...
Here is my gulpfile.js (use Laravels elexir plugin):
mix.scripts([
/*libs*/
'../../../node_modules/jquery/dist/jquery.slim.min.js',
'../../../node_modules/bootstrap/dist/js/bootstrap.min.js',
'../../../node_modules/angular/angular.min.js',
'../../../node_modules/angular-cookies/angular-cookies.min.js',
'../../../node_modules/pickadate/lib/compressed/picker.js',
'../../../node_modules/pickadate/lib/compressed/picker.date.js',
'../../../node_modules/pickadate/lib/compressed/picker.time.js',
'app.js',
'config/*.js',
'angular/controller/*.js'
], 'public/js/app.js');
Here the app.js:
var app = angular.module("app", ['ngCookies'], function ($interpolateProvider) {
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
});
For example here the begin of a controller:
app.controller('someCtrl', function ($scope, $window, $http, $cookies) {
Someone got any idea why this is not working in one file?

When you minify, the controller method names get stripped out. Need to include in this way to have a reference:
app.controller('someCtrl', ['$scope', '$window', '$http', '$cookies'
function ($scope, $window, $http, $cookies) {
// ...
}
]
More here: https://docs.angularjs.org/guide/di

This might be because the system angular uses for injecting dependencies according to the names of the variables passed as parameters. If you are minifying your files into a single one and variables are not keeping the same original name, you should inject the dependencies manually as follow:
var myApp = function ($interpolateProvider) {
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
}
myApp.$inject = ['$interpolateProvider'];
angular.module("app", ['ngCookies'], myApp);
... and in your controller:
app.controller('someCtrl', controlFn);
var controlFn = function ($scope, $window, $http, $cookies) {};
controlFn.$inject = ['$scope', '$window', '$http', '$cookies'];

Related

Inline annotation for angular controller (services)

I am using the generator-angular-fullstack for my app and have come into a problem when minifying / uglyfying my code.
Before minifying my code i could use services and they would work fine but afterwards i get the following error:
[$injector:unpr] Unknown provider: aProvider <- a
I read that i need to add inline annotations to my controller like this (to stop the minify process from destroying the service:
app.controller('mainController', ['$scope', '$http', function($scope, $http) {
$scope.message = 'HOORAY!';
}]);
generator-angular-fullstack creates controllers like this:
(function () {
class EmployeesearchComponent {
constructor($scope, $rootScope, $state, $stateParams, elasticservice, $mdDialog) {
$scope.message = 'HOORAY!';
};
}
angular.module('myApp')
.component('employeesearch', {
templateUrl: 'app/employeesearch/employeesearch.html',
controller: EmployeesearchComponent
});
})();
Where am i supposed to add the services as strings?
Thanks,
I needed to add the strings above the constructor field:
static $inject = ['$scope', '$http']
Another solution is to change the controller key to have an array with the parameters' names and the controller class at the end, like so:
[...]
.component('employeesearch', {
controller: ['$scope', '$rootScope', '$state', '$stateParams', 'elasticservice', '$mdDialog', EmployeesearchComponent]
});
But you should really think about adding these annotations during your build process, it would make you code cleaner. If you're using build systems like gulp or grunt there are libraries that allow you to do this just by adding a single extra line to your build script. You can find it as "ng-annotate".

Working with multiple factories in angular

I was working with only 1 factory in angular, but now that my project has grown too large, I want to split the file in separate factories.
My factories are like this:
angular.module('factories')
.factory('auth', ['$http', '$state', '$window',
function($http, $state, $window) {
var auth = {};
......
return auth;
Userfactory:
angular.module('factories')
.factory('userFactory', ['$http', '$state', '$window',
function($http, $state, $window) {
var userFactory = {};
return userFactory;
I inject them in my controllers:
angular.module('controllers')
.controller('UserCtrl', ['$scope', '$state', 'auth', 'userFactory', 'Facebook',
function ($scope, $state, auth, userFactory, Facebook) {
However I get the following error:
Error: [$injector:unpr]
http://errors.angularjs.org/1.4.7/$injector/unpr?p0=userFactoryProvider%20%3C-%20userFactory%20%3C-%20UserCtrl
I'm also bootstrapping my factories:
angular.module('factories', []);
And I inject factories into app.js:
var app = angular.module('eva', ['ui.router', 'ngMaterial', 'ngMessages',
'controllers', 'factories', 'ngAnimate', '720kb.socialshare',
'angular-loading-bar', 'angular-svg-round-progress', 'pascalprecht.translate',
'facebook']);
What is the proper way to work with multiple factories?
Check if you imported the script into your index file. You need files from both of services to be imported after the angular.js file.
Since factories are in a separate module so you need to set dependency for controller module because it is using factories from factories module.
Do something like
angular.module('controllers', ['factories'])
.controller('UserCtrl', ['$scope', '$state', 'auth', 'userFactory', 'Facebook',
function ($scope, $state, auth, userFactory, Facebook) {

can we define angular dependencies in app.controller level rather then in app.module level?

I'm following this example for ui.grid
site: http://ui-grid.info/docs/#/tutorial/203_pinning
var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.grid.pinning']);
app.controller('MainCtrl', ['$scope', '$http', '$log', function ($scope, $http, $log) {
$scope.gridOptions = {};
I'm using app.js file to define my Common dependencies using in all controllers etc. (whole app)
var app = angular.module("sampleApp", ["ngResource", "ui.router", "ngTouch", "ui.grid", "'ui.grid.pinning'"]);
As you can see "ui.grid" and "ui.grid.pinning" is defined in application or module level. all my controllers/services can use it.
Question:
Is there a way to define these 2 dependencies in controller level? like below, because I'm not going to use it in other controllers/pages....
now I get squeeze underlines in my editor with code below, I assume it's because of the dots(.). it says { expected....
app.controller("empController", ['$scope',
'ui.grid', 'ui.grid.pinning',
function ($scope, ui.grid, ui.grid.pinning) {
You can use the explicit $injector in your controller.
app.controller("empController", function empController($scope, ui.grid, ui.grid.pinning){
empController.inject = ['$scope','ui.grid','ui.grid.pinning'];
}

Angular how to include $http when minifying JS

Since I'm minifying and uglifying my JS, I can't simply do the following:
var app = angular.module('app', []);
app.controller('MyController', function($scope, $http) {
// ...
});
It will throw an inject-related error since minifying it jumbles up the $scope var.
Instead, I have to do this:
app.controller('MyController', ['$scope', function($scope) {
$scope.angularIs = "awesome";
}]);
Question: Using the second approach, how do I add the http service? Something like this?
app.controller('MyController', ['$scope&$http', function($scope, $http) {
// ...
}]);
And can my angular.module('app', []); declaration stay the same, or do I have to add some type of http dependency to the []'s? Thanks!
You can just use:
app.controller('MyController', ['$scope', '$http', function($scope, $http) {
// ...
}]);
It will match then against the arguments inside function(). Your app's dependencies will always be strings, so those will be fine when minified.
use this:
app.controller('MyController', ['$scope','$http', function($scope, $http) {
// ...
}]);

angularjs angular-file-upload Unknown provider: $uploadProvider error

This is not a duplicate of This Question
I have included all the required files in view:
<script src="~/Scripts/angular-file-upload-master/examples/console-sham.min.js"></script>
<script src="~/Content/js/angular.js"></script>
<script src="~/Scripts/angular-file-upload-master/angular-file-upload.js"></script>
My module and controller:
var controllers = angular.module('controllers', ['ngGrid', 'ngDialog', 'angularFileUpload']);
controllers.controller('CustomProductsCtrl',
['$scope', '$window', 'ngDialog', 'CommonService',
'CustomProductsServices', '$upload',
function ($scope, $window, ngDialog, CommonService,
CustomProductsServices, $upload){
});
But still I get this error.
Error: [$injector:unpr] Unknown provider: $uploadProvider
Please help me out.
Hit the same issue, turned out that the documentation to inject $upload is out of date, it should be FileUploader:
controllers.controller('CustomProductsCtrl',
[..., '$upload', function (..., 'FileUploader') {
Spent more time than I'd like to admit figuring that out. FYI, I determined that by looking at angular-file-upload.js:
.factory('FileUploader', ['fileUploaderOptions', '$rootScope', '$http', '$window', '$compile',
It appears that you didn't close the controller declaration correctly.
Specifically, you have: }); when you should have }]); instead. Note the missing ].
In context, you should have:
var controllers = angular.module('controllers', ['ngGrid', 'ngDialog', 'angularFileUpload']);
controllers.controller('CustomProductsCtrl',
['$scope', '$window', 'ngDialog', 'CommonService',
'CustomProductsServices', '$upload',
function ($scope, $window, ngDialog, CommonService,
CustomProductsServices, $upload){
}]); // Note: missing ']' added in here
because we need to follow the form of declaring a controller. The controller API is terse, but pretty succint:
$controller(constructor, locals);
Which expanded to your case:
module_name.controller( 'your_Ctrl',
[locals, function(){
}
]
);
I added in extra spacing to call out the missing ] and to show how we're closing off elements within the declaration.
It seems this error can be ng-file-upload version dependent:
https://github.com/danialfarid/ng-file-upload/issues/45
If you try the suggestions on that page and this page and still get the error, the following worked for me:
angular.module('starter.controllers', ['ngFileUpload'])
.controller('HomeCtrl', function($scope, ... Upload) {
...
file.upload = Upload.upload({...}); //Upload instead of $upload
...
})

Resources