我尝试创建一个UI,在该UI中有一个包含几个文本字段的表单,一个input type="file"
和一个div
,您可以拖放图像以与表单的其余部分一起上传。
我的目标/逻辑
使用相同的div
拖放图像或单击图像,然后像input type="file"
一样打开文件夹资源管理器。在实际上不可能“拖放”的小屏幕上,启用单击是有意义的。并且由于表单中已经存在input type="file"
,因此没有理由从div
中获取图像并将其附加到表单等中。我尝试获取放在{中的图像{1}},将其设置为div
中的值,然后提交一次表单。 (如果用户单击input type="file"
,则div
已经有一个值,因此我可以再次提交表单。)
这是代码
input type="file"
因此,当单击 <div id="imageDrop" (click)='imageInput.click()' (drop)="drop($event)" (dragover)="allowDrop($event)" #imageDrop>
</div>
<input type="file" formControlName="imageInput" required #imageInput id="imageInput" (change)='imageChange($event)' > <!-- use css to hide it -->
时,实际上是通过imageDrop
调用imageChange
这是组件中的打字稿。
(click)='imageInput.click()'
错误
当我尝试拖放图像时,我得到指向该HTML行//imageUpload is the name of the reactive form
acceptedImageTypes = {'image/png': true,'image/jpeg': true,'image/gif': true};
@ViewChild('imageDrop') imageDrop;
allowDrop(e) {
e.preventDefault();
}
drop(e) {
e.preventDefault();
//clear in case we selected something before via click
this.imageUpload.controls.imageInput.reset();
this.imageDrop.innerHTML="";
this.checkfiles(e.dataTransfer.files);
}
imageChange(event){
this.imageDrop.innerHTML="";
this.checkfiles(event.target.files);
}//imageChange
checkfiles(files){
if (this.acceptedImageTypes[files[0].type] !== true){
this.imageDrop.nativeElement.innerHTML="Not an image";
return;
}
else if (files.length>1){
this.imageDrop.nativeElement.innerHTML="Only one image/time";
return;
}
else { this.readfiles(files); }
}//checkfiles
readfiles(files){
const reader = new FileReader();
let image = new Image();
reader.onload = (event) =>{
this.imageDrop.nativeElement.innerHTML="";
let fileReader = event.target as FileReader;
image.src = fileReader.result;
image.width = 150;
this.imageDrop.nativeElement.appendChild(image);
};
reader.readAsDataURL(files[0]);
if (this.imageUpload.controls.imageInput.value==null) {
//if its null then means that we dragging an img, so the previous image from the input file is deleted
//now we got to put this image to the input file in order to submit the form
this.imageUpload.controls.imageInput.reset(files[0] );
}
}//readfiles
imageUploadSubmitted(){
//when form submit, for now just check image value to check if its the right one
console.log('IMAGE VALUE SUBMIT = = ',this.imageUpload.controls.imageInput.value);
}
的{{1}},但我确信它与
ERROR DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string
<div id="imageDrop" (click)='imageInput.click()' (drop)="drop($event)" (dragover)="allowDrop($event)" #imageDrop>
函数的一部分。
有什么想法可以解决此问题,以便文件输入可以获取值,然后可以自由提交表单吗?
谢谢
答案 0 :(得分:8)
好的,给你他错误的那一行是this.imageUpload.controls.imageInput.setValue(files[0]);
原因是,由于安全问题,浏览器将阻止您以编程方式设置文件。
相反,您可以直接使用e.dataTransfer.files
:
let input = this.imageUpload.controls.imageInput as any;
input.files = files;
答案 1 :(得分:1)
您要尝试执行的操作无法通过这种方式实现(由于每个人所说的原因,安全原因等)。
要实现所需的功能,Angular解决方案是通过实现 ControlValueAccessor 创建一个使用[[ngModel)] formControlName的自定义组件。
通过这样做,您将可以将所需的任何内容作为值放入FormControl。
实现ControlValueAccessor是许多教程的一部分:https://blog.angularindepth.com/never-again-be-confused-when-implementing-controlvalueaccessor-in-angular-forms-93b9eee9ee83
在这里您可以找到我自己的一些代码,一个在Form中工作的图像选择器:
示例:https://ng-tools.asi.fr/views/showroom/asi-ngtools/components/asi-image-chooser