Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

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

Closed
pkozlowski-opensource opened this issue Oct 11, 2012 · 14 comments

Comments

@pkozlowski-opensource
Copy link
Member

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
Copy link
Contributor

mhevery commented Oct 14, 2012

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.

@mhevery mhevery closed this as completed Oct 14, 2012
@pkozlowski-opensource
Copy link
Member Author

@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
Copy link
Contributor

mhevery commented Oct 14, 2012

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@git.luolix.topwrote:

@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//issues/1452#issuecomment-9427968.

@petebacondarwin
Copy link
Contributor

@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
Copy link
Contributor

mhevery commented Nov 2, 2012

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.

@mhevery mhevery reopened this Nov 2, 2012
@sudhirj
Copy link
Contributor

sudhirj commented Nov 23, 2012

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

pkozlowski-opensource pushed a commit that referenced this issue Dec 1, 2012
`injector.instantiate` is now called for arrays too, instead of only for functions.

Closes #1452
jbdeboer pushed a commit to jbdeboer/angular.js that referenced this issue Feb 9, 2013
`injector.instantiate` is now called for arrays too, instead of only for functions.

Closes angular#1452
@jintoppy
Copy link

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
Copy link
Contributor

@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
Copy link

dmbjsn commented Nov 25, 2014

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
Copy link
Contributor

@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
Copy link
Member

gkalpak commented Nov 26, 2014

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

@rodyhaddad
Copy link
Contributor

@gkalpak indeed, thanks! :)

@aymone
Copy link

aymone commented Nov 26, 2014

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

try minify, if ok, notify me please.

@prabhakarkarajani
Copy link

@anymone thanks! :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants