Angular code mangled causes "Unknown Provider" message - javascript

I want to mangle my AngularJS file, and it works for almost the whole part. However, when I click through the app and navigate to the only part that uses ngLazyBind and angular-history, I get the following issue: Error: [$injector:unpr] Unknown provider: aProvider <- a <- $lazyBind .
I am using ngMin in hopes that this kind of stuff wouldn't happen. When I set uglify's mangled property to false, this issue goes away.
Another little note - injecting $lazyBind into a controller is what causes the error. I can include lazyBind in the app without issue, but when I inject $lazyBind into a controller the error arises.
The reason I mention angular-history is if I completely eliminate lazyBind, the exact same error appears with Error: [$injector:unpr] Unknown provider: mProvider <- m <- History.

It doesn't look like the 2 libraries are minification-safe...
In angular-history line 88...
angular.module('decipher.history', ['lazyBind']).service('History',
function ($parse, $rootScope, $interpolate, $lazyBind, $timeout, $log,
From the error message, it looks like $parse was renamed to m and angular wasn't able to resolve it.
Same thing with ngLazyBind line 89...
app.factory("$lazyBind", lazyBindProvider);

Related

Use $compileProvider to avoid unsafe links

I have no trouble injecting things like $scope and $location and $routeProvider, why is $compileProvider different?
Based on this answer, I understand that I have to instruct angular to not prefix certain links (sms in my case), but I can't apply the answer in my project. It says I should add this:
angular.module('myModule', [], function ($compileProvider) {
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|file):/);
});
But the chrome console says:
"angular.js:68 Uncaught Error: [$injector:unpr] Unknown provider:
$compileProviderProvider <- $compileProvider"
That "provider-provider" thing made me think that the real name of the service is just $compile (and that angular is tacking on the "provider" suffix:
angular.module('myModule', [], function ($compile) {
$compile.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|file):/);
});
But then, predictably, I guess, I get:
angular.js:13550 TypeError: $compile.aHrefSanitizationWhitelist is not a function
That's because you have to add it as a config:
angular.module('myModule').config(['$compileProvider',
function($compileProvider) {
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|file):/);
}
]);

How to mock REST with angular without affecting templates

I am just trying out angular.
I want to get a list of items and show it in template, just hardcoded that now and want to see how it works with ajax. I dont have a rest server working and is trying to mock ajax call.
I just tried including angular mock e2e, but then looks like its covering get for templates as well and throws an error Error: Unexpected request: GET views/main.html
Is there a simple way I can just mock REST requests and have templates work with usual ajax?
This is not a unit-test or e2e test scenario, more of a back-end less development. I am doing this on main app and not in testing.
My app.js looks like this
'use strict';
var app = angular
.module('sabithangularApp', [
'ngResource', 'ngMockE2E'
]);
app.run(function ($httpBackend) {
var tasks = [{...},{....},{...}
];
$httpBackend.whenGET('/tasks').respond(tasks);
$httpBackend.whenGET(/^\/templates\//).passThrough();
//...
});
and error in console looks like
Error: Unexpected request: GET views/main.html
No more request expected
at $httpBackend (http://127.0.0.1:9000/bower_components/angular-mocks/angular-mocks.js:1177:9)
at sendReq (http://127.0.0.1:9000/bower_components/angular/angular.js:7967:9)
at $http.serverRequest (http://127.0.0.1:9000/bower_components/angular/angular.js:7708:16)
at wrappedCallback (http://127.0.0.1:9000/bower_components/angular/angular.js:11100:81)
at wrappedCallback (http://127.0.0.1:9000/bower_components/angular/angular.js:11100:81)
at http://127.0.0.1:9000/bower_components/angular/angular.js:11186:26
at Scope.$eval (http://127.0.0.1:9000/bower_components/angular/angular.js:12175:28)
at Scope.$digest (http://127.0.0.1:9000/bower_components/angular/angular.js:12004:31)
at Scope.$apply (http://127.0.0.1:9000/bower_components/angular/angular.js:12279:24)
at http://127.0.0.1:9000/bower_components/angular/angular.js:1382:15
You need to add an extra line of code (below all other .whenGET()'s) for this that ignores the mock e2e, something like this:
$httpBackend.whenGET(/.*/).passThrough();
This is a catch-all for any (get) request that is not matched by any other line.
EDIT:
the line below catches all requests starting with 'view/':
$httpBackend.whenGET(/^views\/.*/).passThrough();
As I know you need to use $httpBackend for testing.

AngularJS Error: Unknown provider: aProvider <- a

OK I'm officially bald now, after having been streching my hair out with this infamous problem: The minfied AngularJS app just doesn't work, with this error thown out:
Error: [$injector:unpr] Unknown provider: aProvider <- a
http://errors.angularjs.org/1.2.6/$injector/unpr?p0=aProvider%20%3C-%20a
at http://localhost/my-app/dist/scripts/1bde0e2e.vendor.js:4:11492
at http://localhost/my-app/dist/scripts/1bde0e2e.vendor.js:4:26946
at Object.c [as get] (http://localhost/my-app/dist/scripts/1bde0e2e.vendor.js:4:26250)
at http://localhost/my-app/dist/scripts/1bde0e2e.vendor.js:4:27041
at c (http://localhost/my-app/dist/scripts/1bde0e2e.vendor.js:4:26250)
at Object.d [as invoke] (http://localhost/my-app/dist/scripts/1bde0e2e.vendor.js:4:26496)
at http://localhost/my-app/dist/scripts/1bde0e2e.vendor.js:9:910
at Object.f [as forEach] (http://localhost/my-app/dist/scripts/1bde0e2e.vendor.js:4:11927)
at http://localhost/my-app/dist/scripts/1bde0e2e.vendor.js:9:856
at j (http://localhost/my-app/dist/scripts/1bde0e2e.vendor.js:5:27235)
Lots of other people had this problem as well, but looks like it could be fixed by declaring dependencies as an array instead of bare function parameters, like this:
angular.module('my-app').controller('LoginCtrl', [ '$scope', 'HttpService', function($scope, HttpService) { ... }]);
instead of this:
angular.module('my-app').controller('LoginCtrl', function($scope, HttpService) { ... });
But it doesn't work in my case. I checked all of my scripts (coffee and generated javascripts as well), they all use the proper array-style declaration.
The problem doesn't come from extra packages apparently. I tried moving all extra package references out of <!-- bower:js --> block (so that they are not minified by grunt), yet the problem still remains. Which means, it's my code to blame... But then again, I've tried the (seems to be) only fix available, to no avail.
Any hint, even on how to properly debug this?
Thanks in advance!
Finally I've found the problem. And yes, it's a DI bug which I missed.
To all who may be suffering from the same headache: array-format declaration must be done in $routeProvider's resolve options as well. In my case (CoffeeScript ahead):
app.config (['$routeProvider', ($routeProvider) ->
$routeProvider
.when '/',
templateUrl: 'views/main.html'
controller: 'MainCtrl'
resolve:
groups: ['GroupService', (GroupService) -> # I MISSED THIS
return GroupService.getAll()
]
entries: ['EntryService', (EntryService) -> # AND THIS
return EntryService.getAll()
]
# ...
])
Hope this helps!
This behaviour could come if you use implicit injection, instead of explicit declaring your dependencies. In my experience I faced this kind of problem with particular kind of Angular.js services that return instantiable class (for example to create abstract controller Classes or some other particular cases).
For example: AbstractBaseControllerClass
During minification I had the same problem. I solved using internal declaration of dependency injection.
Hope this helps
For the ones that doesn't like CoffeeScript.
I just took some of my code and put it in.
$stateProvider
.state('screen', {
url: '/user/',
templateUrl: 'user.html',
controller: 'UserController',
controllerAs: 'user',
location: "User",
resolve: ['$q', 'UserService', '$state', '$timeout', authenticateUser
]
})
function authenticateUser($q, UserService, $state, $timeout) {
UserService.getLoginStatus().then(function () {
if (UserService.user) {
console.log("is user");
return $q.when();
} else {
console.log("not user");
$timeout(function () {
// This code runs after the authentication promise has been rejected.
// Go to the log-in page
$state.go('login')
});
return $q.reject()
}
});
}

Angular ngResource still not recognising $resource

My app has this line at the top, like most angular apps. I assume here it's pulling in ngRoute and ngResource
var myApp = angular.module('myApp', ['ngRoute', 'ui.bootstrap', 'ngResource']);
how ever I create a service below:
myApp.factory('NewsService', function($resource) {
return $resource('/api/news/:id', {id: '#id'}, {update: {method: 'PUT'}})
})
and in my console I get this message:
Error: [$injector:unpr] Unknown provider: $resourceProvider <- $resource <- NewsService
In my angular folder I have all the js files associated with angular, from angular-animate.js through to angular-touch.js including obviously angular-resource.js, I'm wondering why it is complaining, or what I can do to narrow down to the specific error.
I'm not using the min files at the moment because the errors aren't verbose enough.
In my controllers I just do this:
function newsCreateController($scope, NewsService) {}
You need to make sure you include the appropriate angular files, and application files in your index.html, eg:
<!-- angular related files -->
<script src="/lib/angular/angular.js"></script>
<script src="/lib/angular-resource/angular-resource.js"></script>
<!-- application related files -->
<script src="/apps/myapp/services/newsservice.js"></script>
<script src="/apps/myapp/app.js"></script>
Obviously this is an example, and depends on your file structure.
Once everything is included, you need to make sure your modules are setup correctly, and injected accordingly.

Compiling AngularJS app with animation module in yeoman gives unknown provider error

Im having trouble compiling an angular app that uses the new animation service in Yeoman. Im using the yo angular:app generator.
Everything is fine when working uncompiled but as soon as I run grunt build. Once compiled an unknown provider error is given when I run the DIST folder. I believe it is because the animation service requires a class name, not a normal name. Anyone come across this or a fix?
I tried the usual dependancy rename so the compiler respects the naming but no luck.
Case 1:
angular.module('App', ['ngAnimate']).animation('.pageCube', function(){
// animation stuff
});
Error: [$injector:unpr] Unknown provider: aProvider <- a <- .pageCube-animation
Case 2:
angular.module('App', ['ngAnimate']).animation('.pageCube', ['.pageCube', function(){
// animation stuff
}]);
Error: $injector:unpr] Unknown provider: .pageCubeProvider <- .pageCube <- .pageCube-animation
Case 3: (never going to work but Provider is found)
angular.module('App', ['ngAnimate']).animation('pageCube', ['pageCube', function(){
// animation stuff
}]);
Error: [$animate:notcsel] Expecting class selector starting with '.' got 'pageCube'.
Notes
I am using: AngularJS v1.2.0-rc.2 which is further along than what yo angular:app installs. This might be something to keep in mind in the future.
Case 2 and 3 are completely wrong, the string after the [ is mainly needed as minify-safe option to function parameters so you would need a pageCube parameter on the function, but since you're far from this approach I guess you're doing something wrong inside the function

Categories