7

I'm trying to add this solution to my angularjs app to solve the angularjs autocomplete issue. I'm not sure what i'm missing or doing wrong because I'm currently getting the error:

Error: Unknown provider: $intervalProvider <- $interval <- inputsWatcher <- inputDirective

Part of my app.js

// Module for the login page
var myapp = angular.module('myapp', []);

myapp.config(["$routeProvider", "$httpProvider", "$provide", function($routeProvider, $httpProvider, $provide) {

    // Setup the routing
    $routeProvider
        .when('/login', 
            {
                title: 'Login',
                controller: 'LoginController',
                templateUrl: 'partials/login.html'
            })
        .when('/signup', 
            {
                title: 'Signup',
                controller: 'SignupController',
                templateUrl: 'partials/signup.html'
            })
        .otherwise({redirectTo: '/login'});

    // This loads the ajax loading image when necessary
    var $http,
    interceptor = ['$q', '$injector', function ($q, $injector) {
        var error;

        function success(response) {
            // get $http via $injector because of circular dependency problem
            $http = $http || $injector.get('$http');
            if($http.pendingRequests.length < 1) {
                $('#loadingWidget').hide();
                $('#loadingBackdrop').hide();
            }
            return response;
        }

        function error(response) {
            // get $http via $injector because of circular dependency problem
            $http = $http || $injector.get('$http');
            if($http.pendingRequests.length < 1) {
                $('#loadingWidget').hide();
                $('#loadingBackdrop').hide();
            }
            return $q.reject(response);
        }

        return function (promise) {
            $('#loadingWidget').show();
            $('#loadingBackdrop').show();
            return promise.then(success, error);
        }
    }];

    $httpProvider.responseInterceptors.push(interceptor);



    // Due to browsers issue, it's impossible to detect without a timeout any changes of autofilled inputs
    // https://github.com/angular/angular.js/issues/1460
    // https://github.com/angular/angular.js/issues/1460#issuecomment-28662156
    // Could break future Angular releases (if use `compile()` instead of `link())
    // TODO support select
    var inputDecoration = ["$delegate", "inputsWatcher", function($delegate, inputsWatcher) {
        var directive = $delegate[0];
        var link = directive.link;

        function linkDecoration(scope, element, attrs, ngModel){
            var handler;
            // By default model.$viewValue is equals to undefined
            if(attrs.type == "checkbox"){
                inputsWatcher.registerInput(handler = function(){
                    var value = element[0].checked;
                    // By default element is not checked
                    if (value && ngModel.$viewValue !== value) {
                        ngModel.$setViewValue(value);
                    }
                });
            }else if(attrs.type == "radio"){
                inputsWatcher.registerInput(handler = function(){
                    var value = attrs.value;
                    // By default element is not checked
                    if (element[0].checked && ngModel.$viewValue !== value) {
                        ngModel.$setViewValue(value);
                    }
                });
            }else{
                inputsWatcher.registerInput(handler = function(){
                    var value = element.val();
                    // By default value is an empty string
                    if ((ngModel.$viewValue !== undefined || value !== "") && ngModel.$viewValue !== value) {
                        ngModel.$setViewValue(value);
                    }
                });
            }

            scope.$on("$destroy", function(){
                inputsWatcher.unregisterInput(handler);
            });

            // Exec original `link()`
            link.apply(this, [].slice.call(arguments, 0));
        }

        // Decorate `link()` don't work for `inputDirective` (why?)
        /*
         directive.link = linkDecoration;
         */
        // So use `compile()` instead
        directive.compile = function compile(element, attrs, transclude){
            return linkDecoration;
        };
        delete directive.link;

        return $delegate;
    }];

    $provide.decorator("inputDirective", inputDecoration);
    $provide.decorator("textareaDirective", inputDecoration);
    //TODO decorate selectDirective (see binding "change" for `Single()` and `Multiple()`)

}]);

myapp.factory("inputsWatcher", ["$interval", "$rootScope", function($interval, $rootScope){
    var INTERVAL_MS = 500;
    var promise;
    var handlers = [];

    function execHandlers(){
        for(var i = 0, l = handlers.length; i < l; i++){
            handlers[i]();
        }
    }

    return {
        registerInput: function registerInput(handler){
            if(handlers.push(handler) == 1){
                promise = $interval(execHandlers, INTERVAL_MS);
            }
        },
        unregisterInput: function unregisterInput(handler){
            handlers.splice(handlers.indexOf(handler), 1);
            if(handlers.length == 0){
                $interval.cancel(promise);
            }
        }
    }
}]);
Catfish
  • 18,876
  • 54
  • 209
  • 353
  • What version of Angular are you using? – dnc253 Feb 04 '14 at 16:46
  • 1.0.8. But i just changed it to 1.2.6 and I now get this error:`Uncaught Error: [$injector:modulerr] Failed to instantiate module myezteam-login due to: Error: [$injector:unpr] Unknown provider: $routeProvider http://errors.angularjs.org/1.2.6/$injector/unpr?p0=%24routeProvider at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.js:78:12 at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.js:3538:19 at getService (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.js:3665:39)....` – Catfish Feb 04 '14 at 16:51
  • Found an answer to that here: http://stackoverflow.com/questions/18481863/failed-to-instantiate-module-injectorunpr-unknown-provider-routeprovider. Can you create an answer that I was using the wrong version of Angular and i'll give you credit? – Catfish Feb 04 '14 at 16:52

1 Answers1

17

The $interval service was added with version 1.2.0-rc.3 (See https://github.com/angular/angular.js/blob/master/CHANGELOG.md#120-rc3-ferocious-twitch-2013-10-14). This error will happen with any version before this.

dnc253
  • 39,967
  • 41
  • 141
  • 157