如何用反应形式以输入type = file填充文件?
我正在一个项目中,我有一个表单来提交数据(锻炼),该表单根据表单建立了一个列表。在这里,您可以查看提交的锻炼并进行编辑。
当您单击“编辑锻炼”时,将打开相同的提交表单,这次填充了所有数据。这是通过将“编辑锻炼”链接到EditComponent
来完成的,然后ngOnInit
检查路径参数。如果路线参数具有id
,则它将使用锻炼数据初始化表单。
一切正常。
我遇到的问题特别与<input type="file"...>
的重新填充有关。
这是我进行编辑时的表单初始化
首先,我将initForm()
上的所有变量都设置为空白,然后如果editMode
为true(如果我 am 编辑),则它将用数据填充这些空变量中的每一个来自服务器(或伪数据)。
private initForm() {
// set all values to empty
let workoutImageUrl = "";
let workoutTitle = "";
let workoutPhase = [];
let workoutType = "";
let workoutDuration = "";
let workoutSpecialty = [];
let workoutDescription = "";
let workoutZwo = "";
// check if in edit mode, and if so, make values equal to database data
if (this.editMode) {
const workout = this.workoutService.getWorkout(this.id);
workoutTitle = workout.title;
workoutImageUrl = workout.imageUrl;
workoutPhase = workout.phase;
workoutType = workout.type;
workoutDuration = workout.duration;
workoutSpecialty = workout.specialty;
workoutZwo = workout.zwo;
workoutDescription = workout.description;
this.imgSrc = workout.imageUrl;
console.log("workout that should be here: ", workout);
}
// Populate form either with empty data or editable data
this.workoutForm = new FormGroup({
title: new FormControl(workoutTitle, Validators.required),
imageUrl: new FormControl(workoutImageUrl),
phase: new FormControl(workoutPhase, Validators.required),
duration: new FormControl(workoutDuration, Validators.required),
type: new FormControl(workoutType, Validators.required),
specialty: new FormControl(workoutSpecialty, Validators.required),
zwo: new FormControl(workoutZwo, Validators.required),
description: new FormControl(workoutDescription, Validators.required)
});
}
当我针对新锻炼(标准形式)执行此操作时,没有问题。当我处于EditMode并尝试如上所述在<input type="file"...>
中重新填充数据时,就会出现问题。
现在,我的workoutImageUrl
或workout.imageUrl
来自FireBase存储指定的网址,因此我可以看到为什么输入类型存在问题。如果我使用本地文件,也会发生同样的情况,无法将其重新填充为文件的输入类型。
我想这是由于安全问题引起的,但是这导致我的表单出现以下错误: 从Chrome:“ ERROR DOMException:无法在'HTMLInputElement'上设置'value'属性:此输入元素接受文件名,该文件名只能以编程方式设置为空字符串。 FF中的错误:“ ERROR DOMException:”试图使用一个不可用或不再可用的对象“
编辑锻炼时,有什么方法可以“重新填充”我的图像?那么该文件会显示为锻炼中的当前项目吗?
像上面提到的,我尝试使用本地图像文件来产生相同的结果。我也尝试过从表单组中完全删除imageUrl,但这对我想要属于表单组没有帮助。我还尝试过将workoutImageUrl
更改为与来自Firebase的imgSrc
相同。如果我想显示当前的锻炼图像,此方法有效,但是在提交时不起作用,因为我收到当前图像为空的错误消息。
Here is a StackBlitz for this project(有点简化)。如果单击列表中的锻炼,则可以选择“管理锻炼”和“编辑锻炼”以进入带有已填写表格的编辑页面(当前不适用于图像上传)。
可以通过WorkoutEditComponent
找到src / app / features / workouts-page / workout-edit
。您可以在此处看到图像上传的逻辑,但是我认为这与特定问题无关。数据库存储在StackBlitz上不起作用,但是图像的上传正在起作用(只是没有保存)。我放入了一个示例API,以使此StackBlitz的工作量降至最低。
WorkoutsListComponent
是显示提交的锻炼列表的地方。
在锻炼时查看该锻炼图像文件时,有什么办法?同时,在编辑表单时不必重新上传图像吗?我将图像设置为显示在编辑页面的底部,但是如果显示在此处,它仍然不会重新上传或使用服务器上的同一图像。我每次都必须重新上传图片。
请告诉我是否有什么我可以解释或解释的东西。
答案 0 :(得分:1)
您需要的是从图像URL重新创建目标文件,然后将其分配给输入文件。
我想到了这个主意:
@ViewChild('fileInput', { static : false}) fileInput : ElementRef; //declaration
private initForm() {
let workoutImageUrl = "";
let workoutTitle = "";
let workoutPhase = [];
let workoutType = "";
let workoutDuration = "";
let workoutSpecialty = [];
let workoutDescription = "";
let workoutZwo = "";
if (this.editMode) {
const workout = this.workoutService.getWorkout(this.id);
workoutTitle = workout.title;
workoutImageUrl = workout.imageUrl;
workoutPhase = workout.phase;
workoutType = workout.type;
workoutDuration = workout.duration;
workoutSpecialty = workout.specialty;
workoutZwo = workout.zwo;
workoutDescription = workout.description;
}
this.workoutForm = new FormGroup({
title: new FormControl(workoutTitle, Validators.required),
imageUrl: new FormControl(''),
phase: new FormControl(workoutPhase, Validators.required),
duration: new FormControl(workoutDuration, Validators.required),
type: new FormControl(workoutType, Validators.required),
specialty: new FormControl(workoutSpecialty, Validators.required),
zwo: new FormControl(workoutZwo, Validators.required),
description: new FormControl(workoutDescription, Validators.required)
});
let image_name = workoutImageUrl.split("/").pop();
image_name = image_name.split('?')[0];
fetch(workoutImageUrl, { mode: 'no-cors'})
.then(res => res.blob())
.then(blob => {
const data = new ClipboardEvent('').clipboardData || new DataTransfer();
data.items.add(new File([blob], image_name));
this.fileInput.nativeElement.files = data.files;
this.fileInput.nativeElement.value = data.files[0];
});
}
PS:我已经在您的stackblitz示例中进行了尝试,它正在运行,希望对您有所帮助。祝你好运!
解决cors问题的另一种方法是使用此方法:
const proxyUrl = 'https://cors-anywhere.herokuapp.com/';
fetch(proxyUrl + workoutImageUrl)
答案 1 :(得分:0)
我建议创建一个返回FormGroup的函数
CREATE TABLE users
( user_id int(5) NOT NULL,
username varchar(25) NOT NULL,
password varchar(30) NOT NULL,
PRIMARY KEY(user_id)
);
您使用
initForm(data:any)
{
data=data || {
workoutImageUrl:'';
workoutTitle:"";
workoutPhase:[];
workoutType:"";
workoutDuration:"";
workoutSpecialty:[];
workoutDescription:"";
workoutZwo:"";
return new FormGroup({
title: new FormControl(data.workoutTitle, Validators.required),
imageUrl: new FormControl(''),
phase: new FormControl(data.workoutPhase, Validators.required),
duration: new FormControl(data.workoutDuration, Validators.required),
type: new FormControl(data.workoutType, Validators.required),
specialty: new FormControl(data.workoutSpecialty, Validators.required),
zwo: new FormControl(data.workoutZwo, Validators.required),
description: new FormControl(data.workoutDescription, Validators.required)
});
}