Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

angularjs

I have a fairly simple Angular application that runs just fine on my dev machine, but is failing with this error message (in the browser console) after I deploy it:

Uncaught Error: [$injector:unpr] http://errors.angularjs.org/undefined/$injector/unpr?p0=tProvider%20%3C-%20t%20%3C-%20%24http%20%3C-%20%24compile

No other message besides that. It happens when the page first loads.

I'm running ASP.NET MVC5, Angular 1.2RC3, and pushing to Azure via git.

Googling hasn't turned up anything interesting.

Any suggestions?

EDIT:

I'm using TypeScript, and defining my dependencies with the $inject variable, e.g.:

export class DashboardCtrl {

    public static $inject = [
        '$scope',
        '$location',
        'dashboardStorage'
    ];

    constructor(
        private $scope: IDashboardScope,
        private $location: ng.ILocationService,
        private storage: IDashboardStorage) {
    }
}

I believe that should (or is intended to) get around the local variable renaming problems that arise during minification and that can cause this error.

That said, it clearly has something to do with the minification process, as when I set BundleTable.EnableOptimizations = true on my dev machine, I can reproduce it.

like image 811
Ken Smith Avatar asked Oct 30 '13 01:10

Ken Smith


4 Answers

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.

like image 58
Stuart Nelson Avatar answered Nov 15 '22 06:11

Stuart Nelson


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.

like image 26
Matt Avatar answered Nov 15 '22 06:11

Matt


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
            };
        }]
    };
});
like image 11
Sandeep K Avatar answered Nov 15 '22 04:11

Sandeep K


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.

like image 10
Schnapz Avatar answered Nov 15 '22 04:11

Schnapz