for 'ng-model for 'DEMO ) (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)._requirements_uri.image)에는 data-uri(!)로 선택한 파일의 내용이 입력됩니다.
이 스크립트는 아무것도 업로드하지 않습니다.모델에는 data-uri(base64)로 인코딩된 파일의 내용만 채워집니다.
http://plnkr.co/CMiHKv2BEidM9SShm9Vv에서 데모를 보실 수 있습니다.
「」를 유효하게 하는 <input type="file">
ng-model
데모ng-model
★★ng-model
는, 「Directive」에서는 .<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의 값을 얻을 수 없게 되었습니다.HTML의 uploadme가 디렉티브에 의해 눈에 띄게 업데이트 되었음에도 불구하고 $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는 파일 데이터를 반환할 뿐만 아니라 파일 데이터 url 또는 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과 마찬가지로 스코프 내의 Atribute 이름을 지정할 수 있습니다.사용방법:
<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, last Modified Date, name, size, type, data를 취득하고 파일 배열을 취득할 수 있도록 했습니다.이러한 추가 기능이 필요하신 분들을 위해, 여기 있습니다.
업데이트: 파일을 선택한 후 다시 선택으로 이동했다가 취소하면 나타나는 것처럼 파일이 선택 취소되지 않는 버그를 발견했습니다.그래서 나는 그것을 수정하기 위해 내 코드를 업데이트했다.
.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하지만 AngularJS 1.4.x 를 사용하도록 할 수 .$provide.decorator
angular.Module.decorator
- John Papa's Angular에 준거하여 방법을 시연하기 위해 이 요지를 썼습니다.JS 스타일 가이드:
(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;
};
}
})();
애초에 왜 이런 일이 없었지?각진JS 지원은 IE9까지만 지원하도록 의도되어 있습니다. 만약 당신이 이 결정에 동의하지 않고 그들이 이것을 그냥 넣었어야 했다고 생각한다면, Angular 2+로 넘어가세요. 왜냐하면 더 나은 현대적인 지원이 말 그대로 Angular 2가 존재하는 이유이기 때문입니다.
문제는 (앞에서 언급한 바와 같이) 파일 API 지원이 없으면 IE9의 베이스라인과 폴리필링으로 인해 코어에 대해 제대로 실행할 수 없다는 것입니다.
또한 크로스 브라우저와 호환되지 않는 방법으로 이 입력을 처리하려고 하면 서드파티 솔루션에서는 더 어려워질 뿐이며, 서드파티 솔루션에서는 핵심 솔루션과의 싸움/비활성화/회피가 필요하게 됩니다.
...
#1236을 닫은 것처럼 이 부분을 닫겠습니다.Angular 2는 최신 브라우저를 지원하도록 구축되어 있으며 이 파일 지원을 쉽게 이용할 수 있습니다.
또는 입력을 받아 onchange 함수를 설정할 수 있습니다.
<input type="file" id="myFileInput" />
document.getElementById("myFileInput").onchange = function (event) {
console.log(event.target.files);
};
이거 해봐, 각도 JS에서 나한텐 잘 돼
let fileToUpload = `${documentLocation}/${documentType}.pdf`;
let absoluteFilePath = path.resolve(__dirname, fileToUpload);
console.log(`Uploading document ${absoluteFilePath}`);
element.all(by.css("input[type='file']")).sendKeys(absoluteFilePath);
언급URL : https://stackoverflow.com/questions/17063000/ng-model-for-input-type-file-with-directive-demo
'code' 카테고리의 다른 글
javascript의 set Timeout과 angularjs의 $timeout 서비스의 차이 (0) | 2023.03.09 |
---|---|
용기 내 angularjs 무한 스크롤 (0) | 2023.03.09 |
스프링 데이터 jpa 스타터에서 javax.persistence-api가 jakarta.persistence-api로 대체된 이유는 무엇입니까? (0) | 2023.03.09 |
폴백 이미지에 대한 각도 지시 (0) | 2023.03.09 |
ui-module:뷰 템플릿이 없는 루트 (0) | 2023.03.09 |