angular / angular.js

AngularJS - HTML enhanced for web apps!
https://angularjs.org
MIT License
58.81k stars 27.49k forks source link

Impossible to inject providers into Module.provider() when array-style DI-annotations are used #1452

Closed pkozlowski-opensource closed 11 years ago

pkozlowski-opensource commented 12 years ago

Problem description

It is impossible to define a provider that depends on another provider in the minified version of an application. The following code:

var myApp = angular.module('myApp', []).provider('crudRouteProvider', ['$routeProvider', function(e) {

    this.doSthWithRouteProvider= function(pathPrefix) {
        //do something with $routeProvider here
    };

    this.$get = function() {
        return {};
    };
}]);

will fail with Uncaught Error: Provider crudRouteProvider must define $get factory method. from myApp. Here is the jsFiddle: http://jsfiddle.net/pkozlowski_opensource/FGkdD/1/

Expected behavior

The unminified version works correctly, here is the jsFiddle: http://jsfiddle.net/pkozlowski_opensource/cHHJJ/ The minified version should behave exactly the same.

mhevery commented 12 years ago

if you set the compilation level to advanced then you have to tell compiler not to rename $get. this['$get'] should do the trick.

This is an issue with configuring the compiler not with angular.

pkozlowski-opensource commented 12 years ago

@mhevery Hmm, I'm probably missing sth but actually this fiddle: http://jsfiddle.net/pkozlowski_opensource/FGkdD/1/ exposes the problem when $get is not renamed (just simulating minifier behavior here).

In fact here is another fiddle without any minifications / variables renamed, just using array-style to specify injectables: http://jsfiddle.net/FGkdD/4/

So if I'm not mistaken the problem is really linked to the usage of the array-style of specifying dependencies... But once again, I might be misinterpreting things....

mhevery commented 12 years ago

I am sorry, but you are not explaining what exactly does not work. Why do you think the compiler is breaking this?

On Sun, Oct 14, 2012 at 2:26 PM, Pawel Kozlowski notifications@github.comwrote:

@mhevery https://github.com/mhevery Hmm, I'm probably missing sth but actually this fiddle: http://jsfiddle.net/pkozlowski_opensource/FGkdD/1/exposes the problem when $get is not renamed (just simulating minifier behavior here).

In fact here is another fiddle without any minifications / variables renamed, just using array-style to specify injectables: http://jsfiddle.net/FGkdD/4/

So if I'm not mistaken the problem is really linked to the usage of the array-style of specifying dependencies... But once again, I might be misinterpreting things....

— Reply to this email directly or view it on GitHubhttps://github.com/angular/angular.js/issues/1452#issuecomment-9427968.

petebacondarwin commented 12 years ago

@mhevery What I believe Pawel is saying is that we are not allowed to use the array form of dependency injection for providers:

angular.module('myApp', []).provider('crudRouteProvider', ['$routeProvider', function(e) { ...

This is not a supported syntax. The only parameters that module.provider accepts is ({string}, {function}), where the function must also have a $get method.

The module.provider function ought to accept a ({string}, {array | function}), where the array is a dependency style injection array.

Pete

mhevery commented 12 years ago

Ahh, this has nothing to do with compiler. The issue is that provider takes a constructor function or an object instance, but it fails to see if it is an array. This is a real issue.

sudhirj commented 11 years ago

Just submitted a fix - I'm guessing we just need to instantiate the array same way we would a normal function.

jintoppy commented 10 years ago

Getting error 'Uncaught Error: Unknown provider: crudRouteProvider from myApp '

http://jsfiddle.net/cHHJJ/2/

var myApp = angular.module('myApp', [])
  myApp.provider('crudRouteProvider', function($routeProvider) {

    this.defineCrudRoutes = function(pathPrefix) {
        //do something with $routeProvider here
        $routeProvider.when(pathPrefix+'/list', {});
        $routeProvider.when(pathPrefix+'/new', {});
        //etc.
    };

    this.$get = function() {
        return {};
    };
});

myApp.config(['crudRouteProvider', function(crudRouteProvider){
    crudRouteProvider.defineCrudRoutes('main');
}]);

Is this correct way?

rodyhaddad commented 10 years ago

@jintoppy simply write myApp.provider('crudRoute', [...], the 'Provider' prefix is added automatically.

If you ever have a similar question or problem, check this section of our contributing guide to know where you can ask it. We want to keep Github issues for bug reports and feature requests. Thanks!

dmbjsn commented 9 years ago

Can someone point out why this is not working? (I want to not hardcode day names in a datepicker I'm using)

app.provider("ngQuickDateDefaults", function($locale) {
    return {
        options: {
            dayAbbreviations: $locale.SHORTDAY
            //dayAbbreviations: ["Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør"]
        }
    }
}

I get (without minifying):

[$injector:modulerr] Failed to instantiate module ngQuickDate due to: [$injector:unpr] Unknown provider: $locale

rodyhaddad commented 9 years ago

@dmbjsn It's because $locale is [not] a constant. Hence you can't inject it when creating a provider. Checking out adamalbrecht/ngQuickDate (which I assume you're using), it seems ngQuickDateDefaults wasn't intended to be used like this.

This type of question should be avoided on the angular.js issue tracker, since it's not really an issue with the framework itself. Please check this Got a Question or Problem? section to see where you can ask your question.

gkalpak commented 9 years ago

@rodyhaddad: You probably meant to write "...is not a constant...". (Just mentioning it to avoid confusion.)

rodyhaddad commented 9 years ago

@gkalpak indeed, thanks! :)

aymone commented 9 years ago
.provider('myProvider', myProvider)
function myProvider() {
        this.$inject=['$location'];
        return{
            $get: function ($location) {
                return $location.absUrl();
            }
        };
    }

try minify, if ok, notify me please.

prabhakarkarajani commented 7 years ago

@anymone thanks! :)