简体   繁体   English

Angular File Upload指令不更新控制器模型

[英]Angular File Upload directive not updating controller model

I am attempting to follow this [tutorial] but can't get it working. 我试图遵循这个[教程],但无法让它工作。

My Angular controller is logging undefined for a model created in my directive. 我的Angular控制器正在为我的指令中创建的模型记录undefined Here is a [JSFiddle] of it working created my author of tutorial. 这是一个[JSFiddle]的工作创建了我的教程作者。

The problem is the view can find $scope.myFile and but controller does not ( $scope.myFile is undefined ). 问题是视图可以找到$scope.myFile但控制器没有( $scope.myFile undefined )。

The view displays {{ myFile.name }} (as just example my-image.jpg ). 视图显示{{ myFile.name }} (仅作为示例my-image.jpg )。 The myFile variable is a JS object containing data on selected file. myFile变量是一个包含所选文件数据的JS对象。 This works fine. 这很好用。 The directive seems to be assigning the model the value of selected file (and thus displays it correctly in view). 该指令似乎是为模型分配所选文件的值(因此在视图中正确显示它)。

<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 input type file can't use ng-model , this directive sets up the model to be associated with an file input, assigning to it every time the file fires change event. 由于输入类型file不能使用ng-model ,因此该指令将模型设置为与file输入关联,并在每次文件触发change事件时为其分配。

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 just log $scope.myFile . 在控制器中我只记录$scope.myFile This is called from the button in the HTML above. 这是从上面HTML中的按钮调用的。 Ideally, I'd be uploading the files to server here, but I can't because $scope.myFile is undefined. 理想情况下,我会在这里将文件上传到服务器,但我不能,因为$scope.myFile是未定义的。

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

Can someone tell me why the view would be recieving $scope.myFile but the controller logs undefined for $scope.myFile ? 有人能告诉我为什么视图会收到$scope.myFile但控制器是否为$scope.myFile记录undefined

I ran into the same problem when trying to access a directive's variable from the controller. 我在尝试从控制器访问指令变量时遇到了同样的问题。 In my case I could make myFile available to the controller, but I had to assign it to scope.$parent.$parent.myFile from within the directive. 在我的情况下,我可以让myFile可用于控制器,但我必须将它分配给scope.$parent.$parent.myFile来自指令。 I didn't want to hard code in a depth of ancestry in order to access the variable, so I ended up using a service to share the variable between directive and controller: 为了访问变量,我不想在祖先的深度硬编码,所以我最终使用服务来共享指令和控制器之间的变量:

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

My directive code changed to use the service instead of attrs.fileModel that was used in the tutorial: 我的指令代码更改为使用服务而不是本教程中使用的attrs.fileModel

.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: 然后,在将fileService注入控制器后,我可以直接从fileService访问该文件:

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

This issue is seen in couple of Angular versions, where file object can't be set the scope variable. 在几个Angular版本中可以看到此问题,其中file对象无法设置范围变量。 As a work around make, pass the field to controller, use this file object to upload ( not from scope) 作为一个解决方法,将字段传递给控制器​​,使用此文件对象上传(而不是从范围)

HTML Form HTML表单

<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 希望这能解决问题

我已经看过该教程但是选择使用这个库使得文件无缝上传: ng-file-upload

Try below solution: HTML code: 尝试以下解决方案:HTML代码:

<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>

Code For Service: 服务代码:

    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 are facing any issue. 如果你们有任何问题,请告诉我。

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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM