Javascript 角度反应表单编辑模式,如何重新填充输入类型=文件?

Javascript 角度反应表单编辑模式,如何重新填充输入类型=文件?,javascript,html,angular,typescript,firebase,Javascript,Html,Angular,Typescript,Firebase,如何在被动表单中使用input type=file重新填充文件 我正在做一个项目,在那里我有一个表格来提交数据(训练),它根据表格建立了一个列表。从那里,您可以进入查看提交的训练,并对其进行编辑 当您单击“编辑训练”时,将打开相同的提交表单,这次将填充所有数据。这是通过将“编辑训练”链接到EditComponent,然后ngOnInit检查路线参数来完成的。如果路线参数具有id,则它将使用训练数据初始化表格 这一切都很好 我遇到的问题特别与的重新填充有关 这是我在编辑时的表单初始化 首先,我将i

如何在被动表单中使用input type=file重新填充文件

我正在做一个项目,在那里我有一个表格来提交数据(训练),它根据表格建立了一个列表。从那里,您可以进入查看提交的训练,并对其进行编辑

当您单击“编辑训练”时,将打开相同的提交表单,这次将填充所有数据。这是通过将“编辑训练”链接到
EditComponent
,然后
ngOnInit
检查路线参数来完成的。如果路线参数具有
id
,则它将使用训练数据初始化表格

这一切都很好

我遇到的问题特别与
的重新填充有关

这是我在编辑时的表单初始化 首先,我将
initForm()
上的所有变量设置为空,然后如果
editMode
为真(如果我正在编辑),那么它将使用来自服务器的数据(或虚拟数据)填充每个空变量

当我为新的训练(标准形式)这样做时,没有问题。当我在EditMode中尝试在上面提到的
中重新填充数据时,就会出现问题

现在,我的
workoutImageUrl
workout.imageUrl
来自FireBase存储中给定的Url,因此我可以了解输入类型存在问题的原因。如果使用本地文件,也会发生同样的情况,无法将其重新填充为文件的输入类型

我想这是由于安全问题造成的,但这导致我的表单出现以下错误: 来自Chrome:“ERROR DomeException:未能设置“HTMLInputElement”的“value”属性:此输入元素接受文件名,该文件名只能通过编程设置为空字符串。” 来自FF:“ERROR DomeException:“试图使用不可用或不再可用的对象”

当我编辑训练时,是否有任何方法可以“重新填充”我的图像?使文件显示为训练中的当前项目

如上所述,我尝试过使用本地图像文件,得到了相同的结果。我还尝试过从表单组中完全删除imageUrl,但这没有帮助,因为我希望它位于表单组中。我还尝试过将
workUtiImageURL
更改为与来自Firebase的
imgSrc
相同。Th如果我想显示当前的训练图像,它可以工作,但是当我提交时它不工作,因为我得到一个错误,当前图像为空

(有点简化)。如果您单击列表中的某项训练,则可以选择“管理训练”和“编辑训练”以进入编辑页面,其中包含已填写的表单(当前不使用图像上载)

可以通过
src/app/features/workouts page/workout edit
找到
workoutitcomponent
。您可以在这里看到图像上传的逻辑,但我认为这与此特定问题无关。数据库存储在StackBlitz上不起作用,但图像上传工作正常我加入了一个示例API,让它在这次StackBlitz中以最低限度的速度工作

WorkoutsListComponent
是显示提交的训练列表的位置

当我在编辑训练时查看此训练图像文件时,是否有办法保留此训练图像文件?同时,不必在编辑表单时重新上传图像?我已将图像设置为显示在编辑页面底部,但如果它显示在此处,它仍然不会从服务器重新上传或使用相同的图像。我会每次都必须重新上传图像


如果有什么我可以解释或解释的,请告诉我。

您需要的是从图像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];
    });
}
附言:我已经在你的stackblitz示例中尝试过了,它正在发挥作用,我希望这会有所帮助。祝你好运

解决cors问题的另一种方法是使用以下方法:

const proxyUrl = 'https://cors-anywhere.herokuapp.com/';
fetch(proxyUrl  + workoutImageUrl)

我建议创建一个返回FormGroup的函数

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)
    });
}
你用

this.form=this.initForm(null) //<--an empty form
this.form=this.initForm(workout ) //<--a form with the data

this.form=this.initForm(null)//您好,这对于本地文件中的图像非常有效,但是对于托管在web上的图像又如何呢?例如,我在stackblitz中更新了图像文件以显示来自firebase存储的图像,但代码无法在查看模式下将其保留在输入中。再次感谢,这是cors策略问题。我已更新我的答案是修复它。我为另一个问题道歉。url显示时使用冒号
,而不是在url上使用斜杠
/
。这使得它无效。有办法解决吗?我没有看到任何东西四处查看。是的,这是正常的,因为WorkUtimageURL具有来自firebase存储的url,我们直接使用它来创建file object由于冒号,文件输入返回为null,很遗憾这不起作用
this.form=this.initForm(null) //<--an empty form
this.form=this.initForm(workout ) //<--a form with the data