0
votes

I am trying to do a file upload using angularjs. But I am getting this error for the past few days and I am unable to resolve:

angular.js:13920 Error: [$injector:unpr] http://errors.angularjs.org/1.5.8/$injector/unpr?p0=fileUploadServiceProvider%20%3C-%20fileUploadService%20%3C-%20appCtrl

at angular.js:38
at angular.js:4511
at Object.d [as get] (angular.js:4664)
at angular.js:4516
at d (angular.js:4664)
at e (angular.js:4688)
at Object.invoke (angular.js:4710)
at S.instance (angular.js:10354)
at p (angular.js:9263)
at g (angular.js:8620)

I only want to read the files uploaded, and store it in the server, and not to link to other URL. I am using Django for my backend. This are my codes:

HTML

<body ng-app="myApp">
    <div ng-controller="appCtrl">
        <input type="file" id="file" name="files" accept="text/*"
               data-url="file" class="upload" ng-model="uploadFile"/>
        <label for="file">
          <span class="glyphicon glyphicon-open" id="selectFile">
          </span>Select a file
        </label>
    </div>
</body>
<script src="../static/js/services/fileUploadService.js"></script>
<script src="../static/js/controllers/fileUploadController.js"></script>
<script src="../static/js/fileModel.js"></script>

Directives:

var app = angular.module('myApp', [])
app.directive("filesInput", function() {
  return {
    require: "ngModel",
    link: function postLink(scope,elem,attrs,ngModel) {
      elem.on("change", function(e) {
        var files = elem[0].files;
        ngModel.$setViewValue(files);
      })
    }
  }
});

Service

var app = angular.module('myApp', [])
app.factory('fileUploadService', function ($rootScope) {
    var _files = [];

    var service = {
        add: add,
        clear: clear,
        upload: upload,
      }

     return service 

     function add(file){
        _files.push(file)
        $rootScope.$broadcast('fileAdded', file.files[0].name)
      }
      function clear(){
        _files = []
      }
      function upload(){
        _files.submit();        
      }

Controller:

var app = angular.module('myApp', [])
app.controller('appCtrl', function ($scope, $rootScope, $http, fileUploadService){
    $scope.$watch('uploadFile', function (newVal, oldVal) {
        var submitBtn = document.getElementById('submitBtn');
        //clear existing files
        fileUploadService.clear()
        if(newVal == true){
            var formdata = new FormData();
            $scope.getTheFiles = function ($files) {
                angular.forEach($files, function (value, key) {
                    formdata.append(key, value);
                });
            };    
            // NOW UPLOAD THE FILES.
            $scope.uploadFile = function () {    
                var request = {
                    method: 'POST',
                    url: file,
                    data: formdata,
                    headers: {
                        'Content-Type': undefined
                    }
                };    
                // SEND THE FILES.
                $http(request)
                    .success(function (d) {
                        alert(d);
                    })
                    .error(function () {
                    });
            }
        }]);
        fileUploadService.add(newVal)
        fileUploadService.upload()
    }
})
2
Is app declared somewhere? I only see uploadComponent moduleBill P
You didn't show the relevant part - The error say that the fileUploadService service was not found. Probably because you didn't add it to your app's dependenciesAlon Eitan
@AlonEitan It's actually in my script, which I've forgot to show. I've added them.user3774763
@BillP yes, controller, service and directive all have var app = angular.module('myApp', [])user3774763

2 Answers

2
votes

By using this:

var app = angular.module('myApp', [])

it creates a new module, so controller, service and directive are registered in a separate module! This results in the injection error as controller cannot inject the service, as it is registered in a different module.

The solution is to only create one module and register all the other components in it, like this:

1st file:

var app = angular.module('myApp', []);
angular.module('myApp').factory('fileUploadService', function ($rootScope) {
   ... 
});

2nd file

angular.module('myApp').controller('appCtrl', function ($scope, $rootScope, $http, fileUploadService){
  ...
});

3rd file:

angular.module('myApp').directive("filesInput", function() {
  ...
});
1
votes

Avoid multiple statements that create the module.

ERRONEOUS

var app = angular.module('myApp', [])
app.directive("filesInput", function() {
  //...
});

var app = angular.module('myApp', [])
app.factory('fileUploadService', function ($rootScope) {
  //...
}};

var app = angular.module('myApp', [])
app.controller('appCtrl', function ($scope, $rootScope, $http, fileUploadService){
  //...
});

The extra angular.module('myApp', []) statements are overwriting existing modules, resulting in the fileUploadService becoming unregistered.

BETTER

angular.module('myApp', [])

angular.module('myApp').directive("filesInput", function() {
  //...
});

angular.module('myApp').factory('fileUploadService', function ($rootScope) {
  //...
}};

angular.module('myApp').controller('appCtrl', function ($scope, $rootScope, $http, fileUploadService){
  //...
});

The statement creating the module must be placed before all the code adding more entities to it.

From the Docs:

Creation versus Retrieval

Beware that using angular.module('myModule', []) will create the module myModule and overwrite any existing module named myModule. Use angular.module('myModule') to retrieve an existing module.

For more information, see