在angularjs中为输入文件创建一个指令

时间:2016-04-19 13:21:50

标签: angularjs

我有很多输入文件,对于每个输入文件,我都有一个预览div。

输入文件只接受图像,所以当我选择一些图像时,我可以在预览div中预览它。

我也希望当我选择一些图像来动态创建它时,我的意思是例如,如果我有这个输入文件:

<input id="identityDocument" name="identityDocument"
                 ui-jq="filestyle" type="file" class="filestyle input-lg" ui-options="{
                    buttonText: '{{'ACTIONS.UPLOAD' | translate}}',
                    iconName: 'fa fa-inbox'
                  }"
                 accept="image/*">

我想为它创建一个名为$scope.candidature.identityDocument

的变量

此范围变量将仅包含我选择的图像的名称,以将其保存在数据库中。

我想使用另一个包含图像数据的范围变量,以便我可以在onchange事件后预览它。

我想要的另一件事是获取输入文件所需的工作,因为不支持使用type="file"服务的输入ng-model

我已完成所有这些工作,其工作原理如下:

这是我输入的html代码:

<div class="row">
        <div class="form-group col-md-4">
          <label for="identityDocument">{{'FME_CANDIDATURE.PERSONAL_INFORMATIONS.IDENTITY_DOCUMENT' |
            translate}}: </label>
          <input id="identityDocument" name="identityDocument"
                 ui-jq="filestyle" type="file" class="filestyle input-lg" ui-options="{
                    buttonText: '{{'ACTIONS.UPLOAD' | translate}}',
                    iconName: 'fa fa-inbox'
                  }"
                 onchange="angular.element(this).scope().setFile(this,'identityDoc')"
                 accept="image/*">
          <p class="help-block" style="color: #ff635d; !important;">
            <span ng-show="step1.identityDocument.$invalid && !step1.identityDocument.$pristine">{{'FME_CANDIDATURE.PERSONAL_INFORMATIONS.IDENTITY_DOCUMENT_ERROR' | translate}}</span>
          </p>
        </div>
        <div class="form-group col-md-4 mb-0">
          <h4 class="custom-font text-greensea"><strong>{{'ACTIONS.PREVIEW' | translate}}</strong></h4>
          <div><img ng-src="{{identityDoc}}" class="md-card-image img-responsive img-thumbnail"
                    alt="{{'ERRORS.NO_PHOTO_SELECTED' | translate}}"></div>

        </div>
      </div>

在这段代码中我有输入文件只接受图像,当我选择一些图像时我调用函数setFile(),这个函数将采用两个参数,当前输入和我想给它的名字& #39;范围(因为ng-model不起作用)。 我有另一个div,它将包含一个img来预览所选图像。

这是setFile()函数的代码:

$scope.setFile = function(element, name) {
      $scope.currentFile = element.files[0];
      let reader = new FileReader();

      reader.onload = function(event) {
        //Converts Angular expression into a function, in our case we convert
        //the string we passed as a variable
        //and then assign a value to the parsed string
        $parse(name).assign($scope, event.target.result);
        //the same as above but instead we passing the name of selected image to the candidature object
        $parse('candidature.'+name).assign($scope, element.value.replace(/^.*[\\\/]/, ''));
        $scope.$apply();

      };
      // when the file is read it triggers the onload event above.
      reader.readAsDataURL(element.files[0]);
    };

这样函数接受输入和一个字符串,在那个html示例中我将第二个参数作为"identityDocument"传递,然后该函数将创建一个名为$scope.identityDocument的变量,它将包含图像数据到预览,以及包含图像名称的$scope.candidature.identityDocument

为此输入文件制作所需的作品我使用了这个指令:

app.directive('validFile',function(){
  return {
    require:'ngModel',
    link:function(scope,el,attrs,ngModel){
      //change event is fired when file is selected
      el.bind('change',function(){
        scope.$apply(function(){
          ngModel.$setViewValue(el.val());
          ngModel.$render();
        });
      });
    }
  }
});

如下:

<input ... accept="image/*" valid-file required>

目前这段代码运行完美,但是我必须在控制器中使用指令和函数,我的问题是,我只能使用一个指令,它可以在不使用该控制器函数的情况下完成所有操作吗?

编辑:

我已将此行$parse(name+'Upload').assign($scope, element.files[0]);添加到setFile函数中,我将其用于上传文件,如下所示:

let file = $scope.identityDocUpload;
      let fd = new FormData();
      fd.append('file', file);
      $http.post('http://localhost:8080/fileUpload', fd, {
          transformRequest: angular.identity,
          headers: {'Content-Type': undefined}
        })
        .success(function () {
        })
        .error(function () {
        });

1 个答案:

答案 0 :(得分:0)

我会建议像

这样的东西
(function () {
    'use strict';

    angular
        .module('myApp')
        .directive('validFile', validFile);

    validFile.$inject = [];

    function validFile() {
        var directive = {
        link: link,
        controller: ValidFileController,
        scope: {
                fileRead: '=',
            }
        };
        ValidFileController.$inject = ['$scope'];
        return directive;

        function link(scope, element, attrs, controller) {
            // do UI-things
        }

         function ValidFileController($scope){
            /* jshint validthis: true */
            var vm = this;
            // do controller things
         }
    }

})();

这是一个带控制器的指令。在这种情况下,您可以在一个指令中执行整个逻辑,而不需要ng-controller

ng-modelinput type="file"不起作用是正确的,但是您完成的代码并不是很好,因为您通过它的html属性访问html中的$scope

因此,您的上传技术可以替换为

 element.bind('change', function (changeEvent) {
            var reader = new FileReader();
            reader.onload = function (loadEvent) {
               scope.$apply(function () {
                    scope.fileRead = loadEvent.target.result;
                 });
            }
            reader.readAsDataURL(changeEvent.target.files[0]);
        });

对于动态模型值,您可以选择不同的方法,例如

$scope['yourAttributeName'] = value;

var the_string = 'my.test';
var model = $parse(the_string);
model.assign($scope, 'test');