I minified and merged all js files in one and included in html nothing is working in site.
There are so many files in js and I dont want include all one by one, so modified and merged all in one.
Is there any other way to decrease number of http calls for js files.
When minifying your AngularJS documents it is important that you follow the docs for dependancy injection, otherwise your code can break. You should make sure you are using the preferred array method an example can be seen below:
someModule.controller('MyController', ['$scope', 'greeter', function($scope, greeter) {
// ...
}]);
As seen in the official Angular JS docs: https://docs.angularjs.org/guide/di.
It seems, that's a reason of implicit dependency injection. According to the Angular JS documentation:
Careful: If you plan to minify your code, your service names will get renamed and break your app.
Use strict dependency injection instead. For example:
angular
.module("MyModule")
.controller("MyCtrl", ["$scope", "$timeout", function ($scope, $timeout) {
...
}]);
More over, consider using ng-annotate that's much easier:
angular
.module("MyModule")
.controller("MyCtrl", function ($scope, $timeout) {
"ngInject";
...
});
To follow up on #dayle-salmon 's answer, if you have your controllers like this
app.controller('DemoCtrl', function(dependency1, dependency2){
// controller code
});
Change it to
app.controller('DemoCtrl', ['dependency1', 'dependency2', function(dependency1, dependency2){
// controller code
}]);
Reason JS minificators usually change the name of the dependency that is injected. And Angular wont have a clue on what the dependency is. So, you manually declare them so it won't cause a problem after minification!
Related
Error: [$compile:multidir] Multiple directives [statbox, statbox] asking for template on:
(On console)
Inside index.html
<script src="js/dashboard/dashboard.module.js"></script>
<script src="js/dashboard/dashboard.component.js"></script>
<script src="js/dashboard/statbox.component.js"></script>
Inside dashboard.module.js
var dashboardModule = angular.module('dashboard', ['ngRoute']);
Inside dashboard.component.js
angular.module('dashboard').component('dashboard', {
templateUrl: 'templates/dashboard/dashboard.template.html',
controller: ['$scope', '$routeParams', '$http', '$rootScope', '$log', function DashboardController($scope, $routeParams, $http, $rootScope, $log) {
...stuff NOT REFERENCING STATBOX by any means...
}]
});
Inside statbox.component.js
angular.module('dashboard').component('statbox', {
templateUrl: 'templates/dashboard/statbox.template.html',
controller: ['$http', '$rootScope', '$log', function StatboxController($http, $rootScope, $log) {
... some random get request ...
}]
});
And inside app.js
var app = angular.module('buttonMasher', ['ngRoute', 'dashboard', ...]);
Inside dashboard.template.html
... stuff ...
<div id="history">
... stuff ...
<p><b>Statbox</b></p>
<statbox></statbox>
</div>
Inside statbox.template.html
<div id="statbox">
<p>{{$ctrl.statboxText}}</p>
What am I doing wrong and why do I get this multiple directives error?
Whenever I comment out <script src="js/dashboard/statbox.component.js"></script>
from the index.html everything works but statbox controller is not getting loaded.
(Full project is here: Github: carloworks/masher - One can clone and run spring with profile "dev" enabled.)
Error: [$compile:multidir] Multiple directives [statbox, statbox]
asking for template on
Most likely it's because you included the .js twice in your index.html and the compiler at the time of binding the directive doesn't know which template to choose.
you should check:
the compiled html page to see if you included twice statbox.js
make sure you don't have multiple spots in your code where you
define the same .component('statbox',{})
Late to the party here but in my case it happened because I stupidly named the directive the same thing as the variable that was being passed into it so when the directive was being used it was trying to recursively include itself!
I had this issue with Typescript. I renamed some ts files and visual studio (2015) kept the old generated js files. Somehow, angular used both new and old js files, and I ended up with this error. I did a clean (which deletes all generated js files), build and it worked!
I'm reading http://www.alexrothenberg.com/2013/02/11/the-magic-behind-angularjs-dependency-injection.html and
it turned out that angularjs dependency injection has problems if you minify your javascript
so I'm wondering if instead of
var MyController = function($scope, $http) {
$http.get('https://api.github.com/repos/angular/angular.js/commits')
.then(function(response) {
$scope.commits = response.data
})
}
you should use
var MyController = ['$scope', '$http', function($scope, $http) {
$http.get('https://api.github.com/repos/angular/angular.js/commits')
.then(function(response) {
$scope.commits = response.data
})
}]
all in all I thought the second snippet was for the old version of angularjs but ....
Should I always use the inject way (the second one) ?
Yes, always! So this way even if your minifer converts $scope to variable a and $http to variable b, their identity is still preserved in the strings.
See this page of AngularJS docs, scroll down to A Note on Minification.
UPDATE
Alternatively, you can use ng-annotate npm package in your build process to avoid this verbosity.
It is safer to use the second variant but it is also possible to use the first variant safely with ngmin.
UPDATE:
Now ng-annotate becomes a new default tool to solve this issue.
Yes, you need to use explicit dependency injection (second variant). But since Angular 1.3.1 you can turn off implicit dependency injection, it's really helpful to solve potential problems with renaming at once (before minification).
Turning off implicit DI, using strictDi config property:
angular.bootstrap(document, ['myApp'], {
strictDi: true
});
Turning off implicit DI, using ng-strict-di directive:
<html ng-app="myApp" ng-strict-di>
Just to point out that if you use
Yeoman
there is no need to do like
var MyController = ['$scope', '$http', function($scope, $http) {
$http.get('https://api.github.com/repos/angular/angular.js/commits')
.then(function(response) {
$scope.commits = response.data
})
}]
because grunt during minify take into account how to manage DI.
Like OZ_ said, Use ngmin to minify all angular js file, like directive.js service.js. After that you can use Closure compiler to optimize it.
ref:
How to minify angularjs scripts
Build with YO
You might want to use $inject as it mentioned here:
MyController.$inject = ['$scope', '$http'];
function MyController($scope, $http) {
$http.get('https://api.github.com/repos/angular/angular.js/commits')
.then(function(response) {
$scope.commits = response.data
})
}
Use Strict Dependency Injection to Diagnose Problems
With Implicit Annotation, code will break when minified.
From the Docs:
Implicit Annotation
Careful: If you plan to minify your code, your service names will get renamed and break your app.
You can add an ng-strict-di directive on the same element as ng-app to opt into strict DI mode.
<body ng-app="myApp" ng-strict-di>
Strict mode throws an error whenever a service tries to use implicit annotations.
This can be useful to determining finding problems.
For more information, see
AngularJS Developer Guide - Using Strict Dependency Injection
AngularJS ng-app Directive API Reference
AngularJS Error Reference - Error: $injector:unpr Unknown Provider
I'm using Meteor, Angular and Ionic. I'm having a hard time changing from state A to state B as I keep getting the error 'only one instance of babel/polyfill is allowed'. I tried cleaning up the following code as much as possible. Note that I can change to other states successfully.
Here's my routes.js file:
.state('create-group', {
url:'/create-group:/:buddyId',
templateUrl: 'client/templates/create-group.ng.html',
controller: 'createGroupCtrl'
})
Here's my State A template:
<ion-item ng-repeat="buddy in buddies" ng-click="createGroup({{buddy}})">
</ion-item>
Here's my State A controller:
angular
.module('app')
.controller('whosDownCtrl', whosDownCtrl);
function whosDownCtrl ($scope, $state, $ionicScrollDelegate, $timeout, $meteor) {
$scope.createGroup = createGroup;
function createGroup(buddy) {
$state.go('create-group', { buddyId: buddy._id});
}
};
Here's my State B controller:
angular
.module('app')
.controller('createGroupCtrl', createGroupCtrl);
function createGroupCtrl ($scope, $stateParams) {
var clickedUser = $stateParams.buddyId;
}
Can anyone see what i'm doing wrong?
Did you manually add a babel/ecmascript package to meteor?
Check your .meteor/packages file and your .meteor/versions file because that error means there are multiple conflicting versions of babel added to your project.
And since all babel related meteor packages are independent wrappers, it is very likely to get such conflict.
Remove the "excess" babel packages and you'll be good to go.
I know this is very old question but I landed here while analysing my issue. Posting here my learning as it may help others.
I was also getting the same error in my project. It was happening because there were issues with correct template and controller resolution.
Here is a related github issue that helped in clarifying: https://github.com/Urigo/angular-meteor/issues/870
Use hardcoded template instead of templateUrl to analyse the issue properly.
I ran into a weird problem that I could not figure out, I could not get a good explanation even after searching on the internet.
I have a application (webpage) which consists of ui-bootstrap's accrodion element which gets the data from a json file by $http request. This part is working perfectly fine. Now I wanted to add a multiselect dropdown and I wanted to use the element provided in ui-select. But when I add the dependencies 'ngSanitize' and 'ui-select' in the module, the application doesn't work. I haven't added any dropdown elements, just the dependencies. I don't understand where the problem is.
The original application controller
var app = angular.module('callApp', ['ui.bootstrap']);
app.controller('firstController', function($scope, $http, $modal, $log) {
//some functions are defined here
});
angular.module('callApp').service('popupService', function () {
//service is defined
});
Then i added the dependencies ngSanitize and ui.select
var app = angular.module('callApp', ['ui.bootstrap', 'ngSanitize', 'ui.select']);
app.controller('firstController', function($scope, $http, $modal, $log) {
//some functions are defined here
});
angular.module('callApp').service('popupService', function () {
//service is defined
});
Now the application doesn't work. I haven't modified any other function or added any elements in the html. Why does such a problem arrive? Is there anything wrong with the declaration?
Have you added the reference to the js files to your html page too?
What errors do you see in the console (press F12)?
If the reference to the js files exist in your html then just check the paths are correctly pointing to the actual path.
Regards,
In my application, I use the AngularJS module Pascal Precht (translate module). I come to you because I can not get in my method myApp.Run of app.js a translation key.
I can do in a controller or a view. But impossible to get it at the initialization of the project. It shows me the key, not correspondence.
Do you have a solution?
Here is my code:
var myApp = angular.module('myApp', ['ngRoute', 'ngAnimate', 'myApp.filters', 'myApp.services', 'myApp.directives', 'pascalprecht.translate']);
// Declare routeProvider
myApp.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/', {templateUrl:'partials/connectView.html', controller:'ConnectController'});
$routeProvider.when('/homeView', {templateUrl:'partials/homeView.html', controller:'HomeController'});
}]);
// Declare translateProvider
myApp.config(['$translateProvider', function($translateProvider) {
$translateProvider.useStaticFilesLoader({
prefix: 'res/localization/lang-',
suffix: '.json'
});
$translateProvider.preferredLanguage('fr_FR');
//$translateProvider.preferredLanguage('en_US');
}]);
// Declare Global variables
myApp.run(['$rootScope', '$filter', function($rootScope, $filter) {
$rootScope.list = false;
etc....
//I'm trying to get translate Key but it doesn't work
console.log($filter('translate')('MY_KEY'));
}]);
My AngularJS version is 1.2.16 (last stable version). Thx
Try injecting the $translate service in app.run().
angular-translate version 1.1.1 and below
myApp.run(['$rootScope', '$translate', '$log', function ($rootScope, $translate, $log) {
$log.debug($translate('MY_KEY'));
}]);
I'd also suggest you to upgrade to the latest version of Pascal Precht's angular-translate. There are some changes in the new version.
angular-translate version 2.0.0 and above
myApp.run(['$rootScope', '$translate', '$log', function ($rootScope, $translate, $log) {
// translate via promises (recommended way)
$translate(['MY_KEY', 'MY_OTHER_KEY'])
.then(function (translation) {
$log.debug(translation.MY_KEY);
});
// translate instantly from the internal state of loaded translation
$log.debug($translate.instant('MY_KEY'));
}]);
See this helpful migration guide.
Why don't you inject the $translate service in the run section
and then call it instead of using the filter?!
console.log($translate('MY_KEY'));
Well, Apparently I can't comment because of reputation issue, we came across something that might be what you are experiencing - since the locale file is downloaded only in the config part of angular, it might not be available (yet) when you call the translate.
We solved this by adding all the locale files upfront (we don't have many and they are small) and in the initialization we just choose the correct one, that way we avoid the problem.
(again this should probably be more of a comment then an answer, but I can't comment...)
This is not a solution for your issue, but if you try the following code in your 'run', you will get an idea, why the translation is not available at the initializing state.
myApp.run(['$rootScope', '$filter','$timeout', function($rootScope, $filter,$timeout) {
$timeout(function(){
alert($filter('translate')('MY_KEY'));
},5000)
}]);
Problem here is, by the time the translation is being loaded the 'run' will be executed. So it cannot be assured that you will get the translation loaded at that time.