Antonio Ortiz Antonio Ortiz - 5 months ago 64
HTML Question

What does Error: [$injector:unpr] Unknown provider: tProvider <- t <- myActiveLinkDirective mean?

Basically I am testing to see how a PROD version of my app is looking; I proceeded to run it through some gulp tasks (minify, strip unused css etc.) and got this error:

Error: [$injector:unpr] Unknown provider: tProvider <- t <- myActiveLinkDirective


Can anyone help with what's going on here?

This is some my angular code:

var rustyApp = angular.module('rustyApp', [
'ngAnimate',
'ngRoute',
'viewController',
'mm.foundation',
'angular-flexslider',
'ui.router']).config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider.when('/', {
title: 'home',
templateUrl: '/partials/home.html',
controller: 'HomeController'
}).when('/work', {
title: 'my work',
templateUrl: '/partials/work.html',
controller: 'WorkController'
}).when('/contact', {
title: 'contact',
templateUrl: '/partials/contact.html',
controller: 'ContactController'
}).otherwise({redirectTo: '/'});
// configure html5 to get links working

$locationProvider.html5Mode(true);

}]);




rustyApp.controller('BasicSliderCtrl', function($scope) {
$scope.slides = [
'../images/sliderContent/1.jpg',
'../images/sliderContent/2.jpg',
'../images/sliderContent/3.jpg',
'../images/sliderContent/4.jpg'
];

});

rustyApp.run(function() {
FastClick.attach(document.body);
});

rustyApp.run(['$location', '$rootScope', function($location, $rootScope) {
$rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
$rootScope.title = current.$$route.title;
});
}]);


rustyApp.controller('HomeController', function($scope) {
$scope.pageClass = 'home';
});
rustyApp.controller('WorkController', function($scope) {
$scope.pageClass = 'work';
});
rustyApp.controller('ContactController', function($scope) {
$scope.pageClass = 'contact';
});

rustyApp.controller('OffCanvasDemoCtrl', function($scope) {});


var OffCanvasDemoCtrl = function($scope) {};

rustyApp.controller('ContactController', function($scope, $http) {
$scope.result = 'hidden'
$scope.resultMessage;
$scope.formData; //formData is an object holding the name, email, subject, and message
$scope.submitButtonDisabled = false;
$scope.submitted = false; //used so that form errors are shown only after the form has been submitted
$scope.submit = function(contactform) {
$scope.submitted = true;
$scope.submitButtonDisabled = true;
if (contactform.$valid) {
$http({
method: 'POST',
url: '../partials/mailer.php',
data: $.param($scope.formData), //param method from jQuery
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
} //set the headers so angular passing info as form data (not request payload)
}).success(function(data) {
console.log(data);
if (data.success) { //success comes from the return json object
$scope.submitButtonDisabled = true;
$scope.resultMessage = data.message;
$scope.result = 'bg-success';
if ($scope.result === 'bg-success') {
$scope.class = "bg-success";
}
// if($scope.result){setTimeout(window.location.reload(true),4000);}
if ($scope.result) {
setTimeout(function() {
window.location.reload(true)
}, 4000);
}
} else {
$scope.submitButtonDisabled = false;
$scope.resultMessage = data.message;
$scope.result = 'bg-danger';
}
});
} else {
$scope.submitButtonDisabled = false;
if ($scope.submitButtonDisabled) {
$scope.class = "bg-danger";
}
$scope.resultMessage = 'Failed Please fill out all the fields.';
$scope.result = 'bg-danger';
}
}
});

var viewController = angular.module('viewController', []);

rustyApp.directive('myActiveLink', function($location) {
return {
restrict: 'A',
scope: {
path: "@myActiveLink"
},
link: function(scope, element, attributes) {
scope.$on('$locationChangeSuccess', function() {
if ($location.path() === scope.path) {
element.addClass('uk-active');
} else {
element.removeClass('uk-active');
}
});
}
};
});
// var $j = jQuery.noConflict();

// $j(function() {
// $j('#Container').mixItUp();

// });

rustyApp.directive('mixItUp', function() {
var directive = {
restrict: 'A',
link: link
};

return directive;

function link(scope, element, attrs) {
var $j = jQuery.noConflict();
var mixContainer = $j('#Container');
mixContainer.mixItUp();
mixContainer.on('$destroy', function() {
mixContainer.mixItUp('destroy');
});

}
});


rustyApp.directive('share', function() {
var directive = {
restrict: 'A',
link: link
};

return directive;

function link(scope, element, attrs) {
var $s = jQuery.noConflict();
// mixContainer.on('$destroy', function() {
// mixContainer.mixItUp('destroy');
// });
var $s = new Share(".share-button", {
networks: {
facebook: {
app_id: "602752456409826",
}
}
});

}
});

rustyApp.directive('animationOverlay', function() {
var directive = {
restrict: 'A',
link: link
};

return directive;

function link(scope, element, attrs) {
var modal = $.UIkit.modal(".modalSelector");

if (modal.isActive()) {
modal.hide();
} else {
modal.show();
}

}
});


UPDATED CODE

var rustyApp = angular.module('rustyApp', [
'ngAnimate',
'ngRoute',
'viewController',
'mm.foundation',
'angular-flexslider',
'ui.router'
]).config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider.when('/', {
title: 'home',
templateUrl: '/partials/home.html',
controller: 'HomeController'
}).when('/work', {
title: 'my work',
templateUrl: '/partials/work.html',
controller: 'WorkController'
}).when('/contact', {
title: 'contact',
templateUrl: '/partials/contact.html',
controller: 'ContactController'
}).otherwise({redirectTo: '/'});
// configure html5 to get links working

$locationProvider.html5Mode(true);

}]);


rustyApp.controller('BasicSliderCtrl', ['$scope',
function($scope) {
$scope.slides = [
'../images/sliderContent/1.jpg',
'../images/sliderContent/2.jpg',
'../images/sliderContent/3.jpg',
'../images/sliderContent/4.jpg'
];

}]);


rustyApp.run(function() {
FastClick.attach(document.body);
});

rustyApp.run(['$location', '$rootScope', function($location, $rootScope) {
$rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
$rootScope.title = current.$$route.title;
});
}]);


rustyApp.controller('HomeController', ['$scope', function($scope) {
$scope.pageClass = 'home';
}]);
rustyApp.controller('WorkController', ['$scope', function($scope) {
$scope.pageClass = 'work';
}]);
rustyApp.controller('ContactController', ['$scope', function($scope) {
$scope.pageClass = 'contact';
}]);
rustyApp.controller('OffCanvasDemoCtrl', ['$scope', function($scope) {}]);


var OffCanvasDemoCtrl = function($scope) {};

rustyApp.controller('ContactController', ['$scope', function($scope, $http) {
$scope.result = 'hidden'
$scope.resultMessage;
$scope.formData; //formData is an object holding the name, email, subject, and message
$scope.submitButtonDisabled = false;
$scope.submitted = false; //used so that form errors are shown only after the form has been submitted
$scope.submit = function(contactform) {
$scope.submitted = true;
$scope.submitButtonDisabled = true;
if (contactform.$valid) {
$http({
method: 'POST',
url: '../partials/mailer.php',
data: $.param($scope.formData), //param method from jQuery
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
} //set the headers so angular passing info as form data (not request payload)
}).success(function(data) {
console.log(data);
if (data.success) { //success comes from the return json object
$scope.submitButtonDisabled = true;
$scope.resultMessage = data.message;
$scope.result = 'bg-success';
if ($scope.result === 'bg-success') {
$scope.class = "bg-success";
}
// if($scope.result){setTimeout(window.location.reload(true),4000);}
if ($scope.result) {
setTimeout(function() {
window.location.reload(true)
}, 4000);
}
} else {
$scope.submitButtonDisabled = false;
$scope.resultMessage = data.message;
$scope.result = 'bg-danger';
}
});
} else {
$scope.submitButtonDisabled = false;
if ($scope.submitButtonDisabled) {
$scope.class = "bg-danger";
}
$scope.resultMessage = 'Failed Please fill out all the fields.';
$scope.result = 'bg-danger';
}
}
}]);

var viewController = angular.module('viewController', []);

rustyApp.directive('myActiveLink', ['$location', function($location) {
return {
restrict: 'A',
scope: {
path: "@myActiveLink"
},
link: function(scope, element, attributes) {
scope.$on('$locationChangeSuccess', function() {
if ($location.path() === scope.path) {
element.addClass('uk-active');
} else {
element.removeClass('uk-active');
}
});
}
};
}]);
// var $j = jQuery.noConflict();

// $j(function() {
// $j('#Container').mixItUp();

// });

rustyApp.directive('mixItUp', function() {
var directive = {
restrict: 'A',
link: link
};

return directive;

function link(scope, element, attrs) {
var $j = jQuery.noConflict();
var mixContainer = $j('#Container');
mixContainer.mixItUp();
mixContainer.on('$destroy', function() {
mixContainer.mixItUp('destroy');
});

}
});


rustyApp.directive('share', function() {
var directive = {
restrict: 'A',
link: link
};

return directive;

function link(scope, element, attrs) {
var $s = jQuery.noConflict();
// mixContainer.on('$destroy', function() {
// mixContainer.mixItUp('destroy');
// });
var $s = new Share(".share-button", {
networks: {
facebook: {
app_id: "602752456409826",
}
}
});

}
});

rustyApp.directive('animationOverlay', function() {
var directive = {
restrict: 'A',
link: link
};

return directive;

function link(scope, element, attrs) {
var modal = $.UIkit.modal(".modalSelector");

if (modal.isActive()) {
modal.hide();
} else {
modal.show();
}

}
});


UPDATE

So I wound using gulp-ng-annotateand it appears to add the syntax which was suggested below :) However when I try a PROD build I don't get any errors or anything, it just fails silently. Can anyone help?

Answer

I posted the generic answer below before I had a chance to see the rest of the code you posted. Yes, indeed you have some controllers and directives that use inference. Change your code to use inline annotation, the $inject property; or less intrusively, use a tool like ng-annotate (thanks @deitch for the pointer).


If you're minifying your code, don't use the inference style of dependency annotation. Use the $inject property or use inline annotation. See https://docs.angularjs.org/api/auto/service/$injector.

Example

Don't rely on inference:

function ($scope, $timeout, myFooService) {
}

Use either inline annotation:

[ '$scope', '$timeout', 'myFooService', function ($scope, $rootScope, myFooService) {
}]

Or the $inject property:

function MyFactory($scope, $timeout, myFooService) {
}

MyFactory.$inject = [ '$scope', '$timeout', 'myFooService' ];

This is because the inference flavour relies on the argument names of the function to be preserved (and match to existing services). You might be losing the original names during minification.