[angularjs] `<input type =“file”/>`에 대한 ng-model (지시문 DEMO 사용)

유형 파일이있는 입력 태그에서 ng-model을 사용하려고했습니다.

<input type="file" ng-model="vm.uploadme" />

그러나 컨트롤러에서 파일을 선택한 후에도 $ scope.vm.uploadme는 여전히 정의되어 있지 않습니다.

컨트롤러에서 선택한 파일을 어떻게 얻습니까?



답변

지시문으로 해결 방법을 만들었습니다.

.directive("fileread", [function () {
    return {
        scope: {
            fileread: "="
        },
        link: function (scope, element, attributes) {
            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]);
            });
        }
    }
}]);

입력 태그는 다음과 같습니다.

<input type="file" fileread="vm.uploadme" />

또는 파일 정의 만 필요한 경우 :

.directive("fileread", [function () {
    return {
        scope: {
            fileread: "="
        },
        link: function (scope, element, attributes) {
            element.bind("change", function (changeEvent) {
                scope.$apply(function () {
                    scope.fileread = changeEvent.target.files[0];
                    // or all selected files:
                    // scope.fileread = changeEvent.target.files;
                });
            });
        }
    }
}]);


답변

이 지시어를 사용합니다.

angular.module('appFilereader', []).directive('appFilereader', function($q) {
    var slice = Array.prototype.slice;

    return {
        restrict: 'A',
        require: '?ngModel',
        link: function(scope, element, attrs, ngModel) {
                if (!ngModel) return;

                ngModel.$render = function() {};

                element.bind('change', function(e) {
                    var element = e.target;

                    $q.all(slice.call(element.files, 0).map(readFile))
                        .then(function(values) {
                            if (element.multiple) ngModel.$setViewValue(values);
                            else ngModel.$setViewValue(values.length ? values[0] : null);
                        });

                    function readFile(file) {
                        var deferred = $q.defer();

                        var reader = new FileReader();
                        reader.onload = function(e) {
                            deferred.resolve(e.target.result);
                        };
                        reader.onerror = function(e) {
                            deferred.reject(e);
                        };
                        reader.readAsDataURL(file);

                        return deferred.promise;
                    }

                }); //change

            } //link
    }; //return
});

다음과 같이 호출하십시오.

<input type="file" ng-model="editItem._attachments_uri.image" accept="image/*" app-filereader />

속성 (editItem.editItem._attachments_uri.image)은 데이터 URI (!)로 선택한 파일의 내용으로 채워집니다.

이 스크립트는 아무 것도 업로드하지 않습니다. 그것은 데이터 인코딩 된 (base64) 파일 인코딩 된 광고의 내용으로 모델을 채 웁니다.

실제 데모를 확인하십시오 :
http://plnkr.co/CMiHKv2BEidM9SShm9Vv


답변

활성화하는 방법 <input type="file">작업ng-model

작동하는 지시문 실무 데모 ng-model

핵심 ng-model지침은 작동하지 않습니다<input type="file"> .

이 사용자 정의 지시어는 가능 ng-model하고, 가능의 추가 혜택을 가지고 ng-change, ng-required그리고 ng-form작업에 대한 지침을<input type="file"> .

angular.module("app",[]);

angular.module("app").directive("selectNgFiles", function() {
  return {
    require: "ngModel",
    link: function postLink(scope,elem,attrs,ngModel) {
      elem.on("change", function(e) {
        var files = elem[0].files;
        ngModel.$setViewValue(files);
      })
    }
  }
});
<script src="//unpkg.com/angular/angular.js"></script>
  <body ng-app="app">
    <h1>AngularJS Input `type=file` Demo</h1>

    <input type="file" select-ng-files ng-model="fileArray" multiple>

    <code><table ng-show="fileArray.length">
    <tr><td>Name</td><td>Date</td><td>Size</td><td>Type</td><tr>
    <tr ng-repeat="file in fileArray">
      <td>{{file.name}}</td>
      <td>{{file.lastModified | date  : 'MMMdd,yyyy'}}</td>
      <td>{{file.size}}</td>
      <td>{{file.type}}</td>
    </tr>
    </table></code>

  </body>


답변

이것은 @ endy-tjahjono의 솔루션에 대한 부록입니다.

나는 uploadme 의 가치를 얻을 수없는 결국 그 범위에서 . 비록 uploadme 눈에 띄게 지침에 의해 업데이트 된 HTML에서, 나는 아직도 $ scope.uploadme에 의해 그 값을 액세스 할 수 없습니다. 그래도 범위에서 값을 설정할 수있었습니다. 신비한 ..?

결과적으로 지시문에 의해 자식 범위가 만들어지고 자식 범위에는 자체 업로드가 있습니다. 있습니다.

해결책은 uploadme 의 가치를 유지하기 위해 기본 요소 대신 객체를 사용하는 것이 었습니다 .

컨트롤러에는 다음이 있습니다.

$scope.uploadme = {};
$scope.uploadme.src = "";

그리고 HTML에서 :

 <input type="file" fileread="uploadme.src"/>
 <input type="text" ng-model="uploadme.src"/>

지시문은 변경되지 않았습니다.

이제 모두 예상대로 작동합니다. $ scope.uploadme를 사용하여 컨트롤러에서 uploadme.src 의 값을 가져올 수 있습니다 .


답변

안녕하세요 여러분 지시를 만들고 bower에 등록했습니다.

이 lib는 입력 파일 모델링뿐만 아니라 파일 데이터뿐만 아니라 파일 dataurl 또는 base 64 모델링에도 도움이됩니다.

{
    "lastModified": 1438583972000,
    "lastModifiedDate": "2015-08-03T06:39:32.000Z",
    "name": "gitignore_global.txt",
    "size": 236,
    "type": "text/plain",
    "data": "data:text/plain;base64,DQojaWdub3JlIHRodW1ibmFpbHMgY3JlYXRlZCBieSB3aW5kb3dz…xoDQoqLmJhaw0KKi5jYWNoZQ0KKi5pbGsNCioubG9nDQoqLmRsbA0KKi5saWINCiouc2JyDQo="
}

https://github.com/mistralworks/ng-file-model/

희망은 당신을 도울 것입니다


답변

이것은 ng-model과 마찬가지로 범위에서 속성 이름을 지정할 수 있도록 약간 수정 된 버전입니다.

    <myUpload key="file"></myUpload>

지령:

.directive('myUpload', function() {
    return {
        link: function postLink(scope, element, attrs) {
            element.find("input").bind("change", function(changeEvent) {
                var reader = new FileReader();
                reader.onload = function(loadEvent) {
                    scope.$apply(function() {
                        scope[attrs.key] = loadEvent.target.result;
                    });
                }
                if (typeof(changeEvent.target.files[0]) === 'object') {
                    reader.readAsDataURL(changeEvent.target.files[0]);
                };
            });

        },
        controller: 'FileUploadCtrl',
        template:
                '<span class="btn btn-success fileinput-button">' +
                '<i class="glyphicon glyphicon-plus"></i>' +
                '<span>Replace Image</span>' +
                '<input type="file" accept="image/*" name="files[]" multiple="">' +
                '</span>',
        restrict: 'E'

    };
});


답변

lodash 또는 밑줄을 사용하여 여러 파일을 입력하는 경우 :

.directive("fileread", [function () {
    return {
        scope: {
            fileread: "="
        },
        link: function (scope, element, attributes) {
            element.bind("change", function (changeEvent) {
                return _.map(changeEvent.target.files, function(file){
                  scope.fileread = [];
                  var reader = new FileReader();
                  reader.onload = function (loadEvent) {
                      scope.$apply(function () {
                          scope.fileread.push(loadEvent.target.result);
                      });
                  }
                  reader.readAsDataURL(file);
                });
            });
        }
    }
}]);