5

Я пытаюсь следовать этому [tutorial], но не могу заставить его работать.Угловая директива загрузки файла не обновляется модель контроллера

Мой угловой контроллер регистрирует undefined для модели, созданной в моей директиве. Вот [JSFiddle] из этого работает созданный мой автор учебника.

Проблема есть вид $scope.myFile, но контроллер не ($scope.myFile is undefined).

Вид отображает {{ myFile.name }} (как пример my-image.jpg). Переменная myFile представляет собой объект JS, содержащий данные по выбранному файлу. Это прекрасно работает. Кажется, что директива присваивает модели значение выбранного файла (и, таким образом, отображает его правильно).

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

Вот директива, которую я получил от этого [tutorial].

Поскольку тип ввода 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]); 
       } 
      }); 
      }); 
     } 
     }; 
    } 
    ]). 

В контроллере я просто войти $scope.myFile. Это вызывается с помощью кнопки в HTML выше. В идеале я бы загрузил файлы на сервер здесь, но я не могу, потому что $scope.myFile не определен.

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

Может кто-нибудь сказать мне, почему мнение будет ПОЛУЧАТЬ $scope.myFile, но журналы контроллера undefined для $scope.myFile?

+0

попробуйте инициализировать мой файл в качестве первой строки вашего контроллера: '$ scope.myFile = {}; 'в основном проблема с точкой – harishr

+1

Я сделал plunkr кода, который вы предоставили, и он отлично работает: http://plnkr.co/edit/o9D2Q6Tzkesm5MTyqXFE?p=preview – EvAlex

+1

Опытный этот вопрос сегодня. Передача 'myFile' в функцию 'uploadDocs()', подобную этой 'uploadDocs (myfile)', казалось, сделала это – Akinwale

ответ

5

Я столкнулся с той же проблемой при попытке получить доступ к переменной директивы от контроллера. В моем случае я мог бы сделать myFile доступным контроллеру, но мне пришлось назначить его scope.$parent.$parent.myFile из директивы.Я не хочу жесткий код в глубину происхождения для того, чтобы получить доступ к переменной, так что я в конечном итоге, используя услугу, чтобы разделить переменную между директивой и контроллером:

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

Моя директива код изменен использовать сервис вместо 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'); 
        } 
       }); 
      }); 
     } 
    }; 
}]) 

Затем, после введения fileService в контроллер я мог получить доступ к файлу непосредственно из fileService:

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

Такая же проблема, когда вы используете ng-annotate, modelSetter не работает для меня, если я не использую службу для обмена переменной. – daisy

+0

Я все еще очень хотел бы знать, ПОЧЕМУ учебник в Q отлично работает (также для меня), но реализован в моем собственном коде, но это не так - я получаю ту же ошибку, что и OP с неопределенным значением $ scope.myFile. Тем не менее, это решение работает и довольно понятно, поэтому Глен выигрывает щедрость. – marlar

0

Я видел, что учебник, но выбрал для использования этой библиотеки ведьму делает загрузку файлов бесшовная: ng-file-upload

0

Попробуйте ниже решения: 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> 

Код для службы:

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

Дайте мне знать, если вы, ребята, столкнулись с какими-либо проблемами.

0

попробуйте этот код

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

Этот вопрос рассматривается в нескольких угловых версиях, где объектный файл не может быть установлен в области видимости переменных. Как Обойти сделать, передать поле на контроллер, используйте этот файл объект для загрузки (не из области)

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> 

Контроллер

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

Надеется, что это решает проблему

Смежные вопросы