0

I am building an Angular service for some re-usable code for an upload named 'UploadService' which gets called within a controller below - even though the service has been loaded in I always get the following error

`UploadService.upload is not a function at h.$scope.uploadImage...)`

My Upload Service (UploadService.js)

abcdServices.service('UploadService', function(ApiService, $http, $localStorage, $location, $timeout, $q, $rootScope, Upload) {

var UploadService = function() {
      this.upload_in_progress = false;
      this.attached_media = {
        photos: [],
        videos: []
      }
  };

  UploadService.prototype.upload = function(files) {
     console.log('get here');

  };

  return UploadService;

});

// My Controller where the service is called - note I have added this to the

    $scope.uploadImage = function(files, fileIndex, imageIndex) {
        console.log('existing upload image');
        console.log(files); // this shows an array in the console log as expected
        UploadService.prototype.upload(files);

    }

// The controller has the service loaded in at the top and I have included UserService.js file in the index.php

abcdControllers.controller('PostController', function( $http, $rootScope, UploadService) {
3
  • Just curious, Why do you need to use prototype in Angular service? Commented Nov 9, 2017 at 11:44
  • @Satpal this was purely from the previous developer that worked on this (no other reason.. I presume using prototype is overkill) Commented Nov 9, 2017 at 11:45
  • No it's not an overkill, prototype is very much a javascript way to add instance members to a "Class". The thing is, you have to use the UploadService.upload() directly not through the prototype UploadService.prototype.upload() because UploadService is not a reference to the class, angularjs' injector gives you an instance of that class. Commented Nov 9, 2017 at 11:50

1 Answer 1

1

The prototype is just a javascript way to add instance members to a "Class". The point is, you have to use the UploadService.upload() directly not through the prototype UploadService.prototype.upload() because UploadService is not a reference to the class, angularjs' injector gives you an instance of that class, when you declare a service UploadService, angularjs injects a singleton reference to new UploadService().

Also, you are declaring the service class in the wrong way, your approach doesn't return the UploadService class for the injector, it only returns a function that returns the UploadService, which is never exposed. A better approach for that would be something like the code bellow:

abcdServices.service('UploadService', function UploadService(ApiService, $http, $localStorage, $location, $timeout, $q, $rootScope, Upload) {    
    this.upload_in_progress = false;
    this.attached_media = {
        photos: [],
        videos: []
    };

    this.upload = function(files) {
        console.log('get here');    
    };    
});

Or you can simply change it to a factory provider and return a new instance of your "Class":

abcdServices.factory('UploadService', function(ApiService, $http, $localStorage, $location, $timeout, $q, $rootScope, Upload) {    
  var UploadService = function() {
      this.upload_in_progress = false;
      this.attached_media = {
        photos: [],
        videos: []
      };
  };

  UploadService.prototype.upload = function(files) {
     console.log('get here');    
  };

  return new UploadService();    
});
Sign up to request clarification or add additional context in comments.

2 Comments

I have tried the second method and still have some issues in related to this question in regards to passing data to the class properties for some reason with cordova file transfer plugin stackoverflow.com/questions/47223486/…
@Zabs this question has nothing to do with your new issues, as far as I can see you don't know much of javascript particularities, your new problem is related to javascript scope definition, Unlike other OOP compliant languages like java and c#, javascript is prototypal, when you use this inside a function, you are referring to the function's scope not the parent scope like java does with classes, that is, this.media_response inside cordova's callback, refer to the callback's this not the service's this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.