"Uncaught Error: [$injector:unpr]" with angular after deployment

Solution 1:

If you follow your link, it tells you that the error results from the $injector not being able to resolve your dependencies. This is a common issue with angular when the javascript gets minified/uglified/whatever you're doing to it for production.

The issue is when you have e.g. a controller;

angular.module("MyApp").controller("MyCtrl", function($scope, $q) {
  // your code
})

The minification changes $scope and $q into random variables that doesn't tell angular what to inject. The solution is to declare your dependencies like this:

angular.module("MyApp")
  .controller("MyCtrl", ["$scope", "$q", function($scope, $q) {
  // your code
}])

That should fix your problem.

Just to re-iterate, everything I've said is at the link the error message provides to you.

Solution 2:

Ran into the same problem myself, but my controller definitions looked a little different than above. For controllers defined like this:

function MyController($scope, $http) {
    // ...
}

Just add a line after the declaration indicating which objects to inject when the controller is instantiated:

function MyController($scope, $http) {
    // ...
}
MyController.$inject = ['$scope', '$http'];

This makes it minification-safe.

Solution 3:

This problem occurs when the controller or directive are not specified as a array of dependencies and function. For example

angular.module("appName").directive('directiveName', function () {
    return {
        restrict: 'AE',
        templateUrl: 'calender.html',
        controller: function ($scope) {
            $scope.selectThisOption = function () {
                // some code
            };
        }
    };
});

When minified The '$scope' passed to the controller function is replaced by a single letter variable name . This will render angular clueless of the dependency . To avoid this pass the dependency name along with the function as a array.

angular.module("appName").directive('directiveName', function () {
    return {
        restrict: 'AE',
        templateUrl: 'calender.html'
        controller: ['$scope', function ($scope) { //<-- difference
            $scope.selectThisOption = function () {
                // some code
            };
        }]
    };
});

Solution 4:

If you have separated files for angular app\resources\directives and other stuff then you can just disable minification of your angular app bundle like this (use new Bundle() instead of ScriptBundle() in your bundle config file):

bundles.Add(
new Bundle("~/bundles/angular/SomeBundleName").Include(
               "~/Content/js/angular/Pages/Web/MainPage/angularApi.js",
               "~/Content/js/angular/Pages/Web/MainPage/angularApp.js",
               "~/Content/js/angular/Pages/Web/MainPage/angularCtrl.js"));

And angular app would appear in bundle unmodified.