Angular File Upload Directive not updating controller model

I am trying to execute this [tutorial] but cannot make it work.

My Angular controller registers undefined for the model created in my directive. Here is the [JSFiddle] from which he created my tutorial author.

The problem is that the view can find $scope.myFile , but the controller is not ( $scope.myFile is undefined ).

The view displays {{ myFile.name }} (as an example, my-image.jpg ). The variable myFile is a JS object containing the data in the selected file. It works great. This directive seems to assign the model the value of the selected file (and thus render it correctly).

 <input file-model="myFile" type="file"/ > <div class="label label-info"> {{ myFile.name }} </div> <button ng-click="uploadDocs()">Click</button> 

Here is the directive I got from this [tutorial] .

Since the input type file cannot use ng-model , this directive sets the model that should be associated with the input file , assigning it every time the file fires a change event.

 directive('fileModel', [ '$parse', function ($parse) { return { restrict: 'A', link: function(scope, element, attrs) { var model = $parse(attrs.fileModel); var modelSetter = model.assign; element.bind('change', function(){ scope.$apply(function(){ if (element[0].files.length > 1) { modelSetter(scope, element[0].files); } else { modelSetter(scope, element[0].files[0]); } }); }); } }; } ]). 

In the controller, I simply register $scope.myFile . This is invoked using the button in the HTML above. Ideally, I would upload the files to the server here, but I cannot, because $scope.myFile is undefined.

 $scope.uploadDocs = function() { var file = $scope.myFile; console.log($scope.myFile); }; 

Can someone tell me why the view will receive $scope.myFile , but the controller will register undefined for $scope.myFile ?

+5
source share
5 answers

I encountered the same problem when trying to access a directory variable from a controller. In my case, I could make myFile available to the controller, but I had to assign it scope.$parent.$parent.myFile from the directive. I did not want to hardcode deep into the family tree to access the variable, so I ended up using the service to exchange the variable between the directive and the controller:

 .factory('fileService', function() { var files = []; return files; }) 

My directive code has changed to use the service instead of attrs.fileModel , which was used in the tutorial:

 .directive('fileModel', ['$parse', 'fileService', function ($parse, fileService) { return { restrict: 'A', link: function(scope, element) { element.bind('change', function(){ scope.$apply(function(){ if (element[0].files != undefined) { fileService.push(element[0].files[0]); console.log('directive applying with file'); } }); }); } }; }]) 

Then, after injecting fileService into the controller, I could access the file directly from fileService:

 $scope.uploadDocs = function() { console.log(fileService); }; 
+5
source

This issue is addressed in several versions of Angular where the file object cannot be set to a scope variable. As work around make, pass the field to the controller, use this file to load (not from scope)

HTML form

 <form> <div class="form-group"> <label for="myFileField">Select a file: </label> <input type="file" file-model="myFile" /> <label>File Name:</label> <input type="text" ng-model="filename"></input> </div> <button ng-click="uploadFile(myFile)" class="btn btn-primary">Upload File</button> </form> 

controller

  $scope.uploadFile = function (file1) { var file = $scope.myFile; // this is undefined console.log("My file =" +file1); // you get this // Make http call to upload the file or make service call } 

Hope this solves the problem

+1
source

I saw this tutorial, but decided to use this library, which makes file uploads seamless: ng-file-upload

0
source

Try below: HTML code:

 <div class="btn-header"> <label for="attachment" class="control-label">Attachment</label> <div class="has-feedback"> <input type="file" id="fileUpload" name="attachment" ng-disabled="BRPTab.BRPTelePhonyandTestScipt.Checked" class="form-control" data-ak-file-model="BRPTab.tutorial.attachment" /> <span class="form-control-feedback" aria-hidden="true"></span> <div class="help-block with-errors"></div> </div> </div> 

Service Code:

  AppService.factory("entityService", ["akFileUploaderService", function(akFileUploaderService) { var saveTutorial = function(tutorial, url) { return akFileUploaderService.saveModel(tutorial, url); }; return { saveTutorial: saveTutorial }; }]); (function() { "use strict" angular.module("akFileUploader", []) .factory("akFileUploaderService", ["$q", "$http", function($q, $http) { var getModelAsFormData = function(data) { var dataAsFormData = new FormData(); angular.forEach(data, function(value, key) { dataAsFormData.append(key, value); }); return dataAsFormData; }; var saveModel = function(data, url) { var deferred = $q.defer(); $http({ url: url, method: "POST", //data: // { // tutorial: getModelAsFormData(data), // Object: Obj // }, //params: Indata, data: getModelAsFormData(data), transformRequest: angular.identity, headers: { 'Content-Type': undefined } }).success(function(result) { deferred.resolve(result); }).error(function(result, status) { deferred.reject(status); }); return deferred.promise; }; return { saveModel: saveModel } } ]) .directive("akFileModel", ["$parse", function($parse) { return { restrict: "A", link: function(scope, element, attrs) { var model = $parse(attrs.akFileModel); var modelSetter = model.assign; element.bind("change", function() { scope.$apply(function() { modelSetter(scope, element[0].files[0]); }); }); } }; } ]); })(window, document); 

Let me know if you guys encounter any problem.

0
source

try this code

  <html> <head> <script src = "https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script> </head> <body ng-app = "myApp"> <div ng-controller = "myCtrl"> <input type = "file" file-model = "myFile"/> <button ng-click = "uploadFile()">upload me</button> </div> <script> var myApp = angular.module('myApp', []); myApp.directive('fileModel', ['$parse', function ($parse) { return { restrict: 'A', link: function(scope, element, attrs) { var model = $parse(attrs.fileModel); var modelSetter = model.assign; element.bind('change', function(){ scope.$apply(function(){ modelSetter(scope, element[0].files[0]); }); }); } }; }]); myApp.service('fileUpload', ['$http', function ($http) { this.uploadFileToUrl = function(file, uploadUrl){ var fd = new FormData(); fd.append('file', file); $http.post(uploadUrl, fd, { transformRequest: angular.identity, headers: {'Content-Type': undefined} }) .success(function(){ }) .error(function(){ }); } }]); myApp.controller('myCtrl', ['$scope', 'fileUpload', function($scope, fileUpload){ $scope.uploadFile = function(){ var file = $scope.myFile; console.log('file is ' ); console.dir(file); var uploadUrl = "/fileUpload"; fileUpload.uploadFileToUrl(file, uploadUrl); }; }]); </script> </body> </html> 
0
source

Source: https://habr.com/ru/post/1207557/


All Articles