how to fix Angular not using explicit annotation and cannot be invoked in strict mode

52,442

Solution 1

From the documentation it looks like you need to declare all dependency injections in string array.

There are other ways but normally I would do it like this:

controller: ['$scope', '$element', '$attrs', 'mouseCapture',
  function($scope, $element, $attrs, mouseCapture) {
    ...
  }
]

One of the reason we do this is because when we try to minify this js file, variable names would be reduced to one or 2 characters, and DI needs the exact name to find the services. By declaring DI in a string array, angular can match services with their minified variable name. For this reason, the string array and the function arguments need EXACT MATCHING in number and order.


Update:

If you are following John Papa's Angular style guide, you should do it like this:

controller: MouseCaptureController,
...

MouseCaptureController.$inject = ['$scope', '$element', '$attrs', 'mouseCapture'];

function MouseCaptureController($scope, $element, $attrs, mouseCapture) {
  ...
}

Solution 2

The code says:

$injector:strictdi

There is an error with the dependency injection In the documentation for this error:

Strict mode throws an error whenever a service tries to use implicit annotations

You should try to switching to:

.factory('mouseCapture', ['$rootScope', function ($rootScope) {...}]);

syntax, whenever in strict mode.

Solution 3

Just add 'ngInject' to the first line of your constructor.

Solution 4

adding 'ngInject' was the answer the worked for me. Actually I am using typescript with angularjs, and adding /@ngInject/ right before the constructor did the trick.

Share:
52,442
Mr Mixin
Author by

Mr Mixin

Updated on October 12, 2020

Comments

  • Mr Mixin
    Mr Mixin over 3 years

    I am using strict mode and Angular 1.4.7 , I get the following error:

    Error: [$injector:strictdi] function($scope, $element, $attrs, mouseCapture) is not using explicit annotation and cannot be invoked in strict mode
    

    The angular generated url for the error is:

    https://docs.angularjs.org/error/$injector/strictdi?p0=function($scope,%20$element,%20$attrs,%20mouseCapture

    And the following is the service

    angular.module('mouseCapture', [])
    
    //
    // Service used to acquire 'mouse capture' then receive dragging events while the mouse is captured.
    //
    .factory('mouseCapture', function ($rootScope) {
    
        //
        // Element that the mouse capture applies to, defaults to 'document' 
        // unless the 'mouse-capture' directive is used.
        //
        var $element = document; 
    
        //
        // Set when mouse capture is acquired to an object that contains 
        // handlers for 'mousemove' and 'mouseup' events.
        //
        var mouseCaptureConfig = null;
    
        //
        // Handler for mousemove events while the mouse is 'captured'.
        //
        var mouseMove = function (evt) {
    
            if (mouseCaptureConfig && mouseCaptureConfig.mouseMove) {
    
                mouseCaptureConfig.mouseMove(evt);
    
                $rootScope.$digest();
            }
        };
    
        //
        // Handler for mouseup event while the mouse is 'captured'.
        //
        var mouseUp = function (evt) {
    
            if (mouseCaptureConfig && mouseCaptureConfig.mouseUp) {
    
                mouseCaptureConfig.mouseUp(evt);
    
                $rootScope.$digest();
            }
        };
    
        return {
    
            // 
            // Register an element to use as the mouse capture element instead of 
            // the default which is the document.
            //
            registerElement: function(element) {
    
                $element = element;
            },
    
            //
            // Acquire the 'mouse capture'.
            // After acquiring the mouse capture mousemove and mouseup events will be 
            // forwarded to callbacks in 'config'.
            //
            acquire: function (evt, config) {
    
                //
                // Release any prior mouse capture.
                //
                this.release();
    
                mouseCaptureConfig = config;
    
                // 
                // In response to the mousedown event register handlers for mousemove and mouseup 
                // during 'mouse capture'.
                //
                $element.mousemove(mouseMove);
                $element.mouseup(mouseUp);
            },
    
            //
            // Release the 'mouse capture'.
            //
            release: function () {
    
                if (mouseCaptureConfig) {
    
                    if (mouseCaptureConfig.released) {
                        //
                        // Let the client know that their 'mouse capture' has been released.
                        //
                        mouseCaptureConfig.released();
                    }
    
                    mouseCaptureConfig = null;
                }
    
                $element.unbind("mousemove", mouseMove);
                $element.unbind("mouseup", mouseUp);
            },
        };
    })
    
    //
    // Directive that marks the mouse capture element.
    //
    .directive('mouseCapture', function () {
      return {
        restrict: 'A',
    
        controller: function($scope, $element, $attrs, mouseCapture) {
    
            // 
            // Register the directives element as the mouse capture element.
            //
            mouseCapture.registerElement($element);
    
        },
      };
    })
    ;
    

    How do i fix this error

  • Mr Mixin
    Mr Mixin over 8 years
    Thanks, this was however not enough. I needed to also add the notation to the controller as @lcycool showed
  • lebobbi
    lebobbi over 8 years
    yes, totally. You should use this explicit syntax anywhere there is a dependency injection and you are using strict mode.
  • Gary
    Gary about 8 years
    This worked for my directive as well :) I assume it would work for any Provider (e.g. Service, Factory)
  • Saeed Neamati
    Saeed Neamati about 8 years
    One question, how to find which service is the culprit? In my scenario, Angular shows a call stack that is only filled with angular methods calls. I can't find what service.
  • Icycool
    Icycool about 8 years
    @SaeedNeamati normally angular errors come with links like https://docs.angularjs.org/error/..., click inside and read the error message. Sometimes the real error is a few layer inside.
  • Saeed Neamati
    Saeed Neamati about 8 years
    Yeah, I know that. However when I click on it, the entire callstack is related to anguarjs. I don't know which part of my code brought me here.
  • Icycool
    Icycool about 8 years
    @SaeedNeamati Sometimes angular fails to show meaningful error when it can't parse your template. Or you can paste your error link here?
  • runchu
    runchu about 5 years
    one question, I export a controller as a module and use/import it in bar.component.js like: let {..., controller: controller,...} and I get the same error, how can I solve that?
  • GarfieldKlon
    GarfieldKlon almost 3 years
    I'm also getting this error when using a class: angular.module('my.system').provider( 'ISupportService', class ISupportProvider implements IServiceProvider {... And if I'm turning it into a function that returns an object I get this error: TypeError: Function.prototype.bind.apply(...) is not a constructor
  • Icycool
    Icycool almost 3 years
    @GarfieldKlon not sure if you should put a class on the second argument, it should be a function with specific things expected inside docs.angularjs.org/guide/providers#provider-recipe