Search code examples
angularjsangularjs-directiveangular-promiseangular-resourceangular-services

Angular JS service dependency injection error


I am new to angular I have been trying to do asynchronous validation for username availability and I am getting "Cannot read property 'userName' of undefined" Here is my service code

webAppServices.factory('services', ['$resource',
function ($resource){
    return{
        users: $resource('http://localhost:8080/api/users',{},{
            get:{method:'GET',isArray:true},
            add:{method:'POST',isArray:false},
            update:{method:'POST',isArray:false}
        }),

       userName:$resource('http://localhost:8080/api/users/check/:username',{},{
            check:{method:'GET',isArray:false}
        })
    };}]);

Here is my directive code which passes username for validation

webAppValidation.directive('checkUsername', ['services',
function ($q, services) {
    return {
        require: "ngModel",
        link: function (scope, elm, attrs, ctrl) {
            ctrl.$asyncValidators.checkUsername = function(modelValue, viewValue){
               //check username
                return ctrl.$isEmpty(modelValue) || services.userName.check({username:modelValue}).
                        then(function resolved(){
                            //username exists, this means validation fails
                            return $q.reject('exists');
                        }, function rejected(){
                            //username does not exists, therefore this validation passes
                            return true;
                        });
            };
        }
    };
}]);

And this is what I am getting in Console

TypeError: Cannot read property 'userName' of undefined
at link.ctrl.$asyncValidators.checkUsername (validations.js:56)
at angular.js:24723
at forEach (angular.js:350)
at processAsyncValidators (angular.js:24722)
at NgModelController.$$runValidators (angular.js:24681)
at NgModelController.$$parseAndValidate (angular.js:24819)
at NgModelController.$commitViewValue (angular.js:24787)
at angular.js:24920
at Scope.$get.Scope.$eval (angular.js:15719)
at Scope.$get.Scope.$apply (angular.js:15818)

Solution

  • You are not injecting the $q service.

    webAppValidation.directive('checkUsername', ['$q','services', ...
    

    I would write it like this

    webAppServices.factory('usersService', ['$q','$http',
    
      var endPoint = 'http://localhost:8080/api/user';
    
      function ($q, $http){
        var _getUsers = function(){
           var deffered = $q.defer();
    
           $http.get(endpoint)
                .then(
                  function(data){ deffered.resolve(data);}),
                  function(data){ deffered.reject(data);})
                ).catch(function(error){  $q.reject(error);});
    
           deffered.promise;
    
     }
     //...
     //the other methods
     //...
        return{
           getUsers: _getUsers
           //...
        }
    ;}]);
    

    Although $http returns a promise, is better to return with $q a thenable object to follow the specifications of promises, so the users of your services didnt be confused seeing then ... undefined