유형 파일이있는 입력 태그에서 ng-model을 사용하려고했습니다.
<input type="file" ng-model="vm.uploadme" />
그러나 컨트롤러에서 파일을 선택한 후에도 $ scope.vm.uploadme는 여전히 정의되어 있지 않습니다.
컨트롤러에서 선택한 파일을 어떻게 얻습니까?
유형 파일이있는 입력 태그에서 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
ngModel
'의 $render
기능은?
<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 의 값을 가져올 수 있습니다 .
$scope.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/
희망은 당신을 도울 것입니다
reader.readAsDataURL
방법은 더 이상 사용되지 않습니다. 최신 코드는 URL.create--ObjectURL ()을 사용 합니다.
이것은 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);
});
});
}
}
}]);
function filesModelDirective(){
return {
controller: function($parse, $element, $attrs, $scope){
var exp = $parse($attrs.filesModel);
$element.on('change', function(){
exp.assign($scope, this.files[0]);
$scope.$apply();
});
}
};
}
app.directive('filesModel', filesModelDirective);
여러 입력에서 동일한 작업을 수행해야했기 때문에 @ Endy Tjahjono 메서드를 업데이트했습니다. 읽은 모든 파일이 포함 된 배열을 반환합니다.
.directive("fileread", function () {
return {
scope: {
fileread: "="
},
link: function (scope, element, attributes) {
element.bind("change", function (changeEvent) {
var readers = [] ,
files = changeEvent.target.files ,
datas = [] ;
for ( var i = 0 ; i < files.length ; i++ ) {
readers[ i ] = new FileReader();
readers[ i ].onload = function (loadEvent) {
datas.push( loadEvent.target.result );
if ( datas.length === files.length ){
scope.$apply(function () {
scope.fileread = datas;
});
}
}
readers[ i ].readAsDataURL( files[i] );
}
});
}
}
});
Endy의 지시문을 수정하여 Last Modified, lastModifiedDate, 이름, 크기, 유형 및 데이터를 얻을 수있을뿐만 아니라 파일 배열을 얻을 수있었습니다. 이러한 추가 기능이 필요한 사용자에게는 여기로 이동하십시오.
업데이트 : 파일을 선택한 다음 다시 선택하지만 다시 취소하면 파일이 표시된 것처럼 선택 해제되지 않는 버그가 발견되었습니다. 그래서 코드를 업데이트하여 문제를 해결했습니다.
.directive("fileread", function () {
return {
scope: {
fileread: "="
},
link: function (scope, element, attributes) {
element.bind("change", function (changeEvent) {
var readers = [] ,
files = changeEvent.target.files ,
datas = [] ;
if(!files.length){
scope.$apply(function () {
scope.fileread = [];
});
return;
}
for ( var i = 0 ; i < files.length ; i++ ) {
readers[ i ] = new FileReader();
readers[ i ].index = i;
readers[ i ].onload = function (loadEvent) {
var index = loadEvent.target.index;
datas.push({
lastModified: files[index].lastModified,
lastModifiedDate: files[index].lastModifiedDate,
name: files[index].name,
size: files[index].size,
type: files[index].type,
data: loadEvent.target.result
});
if ( datas.length === files.length ){
scope.$apply(function () {
scope.fileread = datas;
});
}
};
readers[ i ].readAsDataURL( files[i] );
}
});
}
}
});
좀 더 우아하고 통합 된 것을 원한다면 데코레이터 를 사용하여에 input
대한 지원으로 지시문 을 확장 할 수 있습니다 type=file
. 명심해야 할 주된주의 사항은 IE9가 File API를 구현하지 않았기 때문에이 메소드는 IE9에서 작동하지 않는다는 것 입니다. JavaScript를 사용하여 XHR을 통해 유형에 관계없이 이진 데이터를 업로드하는 것은 IE9 또는 이전 버전에서는 기본적으로 불가능합니다.ActiveXObject
합니다. 로컬 파일 시스템에 액세스하는 것은 ActiveX를 사용하는 것이 보안 문제를 요구하는 것으로 간주되지 않습니다.
이 정확한 방법에는 AngularJS 1.4.x 이상이 필요하지만 이것을 $provide.decorator
대신 사용하도록 조정할 수 있습니다 -John Papa의 AngularJS 스타일 가이드 를 준수하면서 수행하는 방법을 보여주기 위해이 요점 을 angular.Module.decorator
작성 했습니다 .
(function() {
'use strict';
/**
* @ngdoc input
* @name input[file]
*
* @description
* Adds very basic support for ngModel to `input[type=file]` fields.
*
* Requires AngularJS 1.4.x or later. Does not support Internet Explorer 9 - the browser's
* implementation of `HTMLInputElement` must have a `files` property for file inputs.
*
* @param {string} ngModel
* Assignable AngularJS expression to data-bind to. The data-bound object will be an instance
* of {@link https://developer.mozilla.org/en-US/docs/Web/API/FileList `FileList`}.
* @param {string=} name Property name of the form under which the control is published.
* @param {string=} ngChange
* AngularJS expression to be executed when input changes due to user interaction with the
* input element.
*/
angular
.module('yourModuleNameHere')
.decorator('inputDirective', myInputFileDecorator);
myInputFileDecorator.$inject = ['$delegate', '$browser', '$sniffer', '$filter', '$parse'];
function myInputFileDecorator($delegate, $browser, $sniffer, $filter, $parse) {
var inputDirective = $delegate[0],
preLink = inputDirective.link.pre;
inputDirective.link.pre = function (scope, element, attr, ctrl) {
if (ctrl[0]) {
if (angular.lowercase(attr.type) === 'file') {
fileInputType(
scope, element, attr, ctrl[0], $sniffer, $browser, $filter, $parse);
} else {
preLink.apply(this, arguments);
}
}
};
return $delegate;
}
function fileInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {
element.on('change', function (ev) {
if (angular.isDefined(element[0].files)) {
ctrl.$setViewValue(element[0].files, ev && ev.type);
}
})
ctrl.$isEmpty = function (value) {
return !value || value.length === 0;
};
}
})();
왜 이것이 처음부터 이루어지지 않았습니까? AngularJS 지원은 IE9까지만 지원됩니다. 이 결정에 동의하지 않고 어쨌든이 결정을 내려야한다고 생각한다면, 더 나은 현대적 지원이 문자 그대로 Angular 2가 존재하는 이유 때문에 왜건을 Angular 2+로 뛰어 넘습니다.
문제는 (앞서 언급했듯이) 파일 API 지원 없이이 작업을 올바르게 수행하는 것이 우리의 기준선이 IE9 이고이 내용을 polyfilling하면 코어에 적합하지 않다는 것입니다.
또한 브라우저 간 호환되지 않는 방식으로이 입력을 처리하려고하면 타사 솔루션의 경우 더욱 어려워 져서 핵심 솔루션과 싸우거나 비활성화 / 해결해야합니다.
...
우리가 # 1236을 닫은 것처럼 이것을 닫을 것입니다. Angular 2는 최신 브라우저를 지원하기 위해 구축되고 있으며 해당 파일 지원으로 쉽게 사용할 수 있습니다.