Angular Реактивный режим редактирования формы, как повторно заполнить тип ввода = файл? - PullRequest
2 голосов
/ 22 февраля 2020

Как я могу заполнить свой файл с типом ввода = файл в реактивной форме?

Я работаю над проектом, в котором у меня есть форма для отправки данных (тренировки), которая формирует список в соответствии с сформироваться. Оттуда вы можете go войти, чтобы просмотреть отправленные тренировки и отредактировать их.

Когда вы нажимаете «Редактировать тренировку», открывается та же самая форма отправки, которая на этот раз заполняется всеми данными. Это делается путем привязки «Редактировать тренировку» к EditComponent, а затем ngOnInit проверяет параметры маршрута. Если у параметров маршрута есть id, то форма инициализируется с данными тренировки.

Все это работает просто отлично.

Проблема, с которой я столкнулся, имеет отношение именно к заселению <input type="file"...>.

Вот моя инициализация формы, когда я go редактирую Сначала я устанавливаю все переменные пустыми на initForm(), затем, если editMode истинно (если I я редактирую), затем он заполнит каждую из этих пустых переменных данными, поступающими с сервера (или фиктивными данными).


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

Когда я сделаю это для новой тренировки (стандартная форма) , нет проблем. Проблема возникает, когда я нахожусь в режиме редактирования и пытаюсь заполнить данные в <input type="file"...>, как указано выше.

Прямо сейчас мой workoutImageUrl или workout.imageUrl исходит из URL-адреса, полученного из моего хранилища FireBase, поэтому я могу понять, почему здесь возникает проблема с типом ввода. То же самое происходит, если я использую локальный файл, он не может быть повторно заполнен в тип ввода файла.

Я предполагаю, что это связано с проблемами безопасности, но это приводит к тому, что моя форма получает следующую ошибку: от Chrome: «ОШИБКА DOMException: не удалось установить свойство« value »для« HTMLInputElement »: это элемент input принимает имя файла, которое может быть программно установлено только в пустую строку. " from FF: «ERROR DOMException:« Предпринята попытка использовать объект, который больше не пригоден для использования »

Можно ли каким-либо образом« повторно заполнить »мое изображение, когда я редактирую тренировки? Таким образом, файл отображается как текущий элемент в тренировке?

Как упоминалось выше, я попытался использовать локальные файлы изображений, которые дают тот же результат. Я также попытался полностью удалить imageUrl из группы форм, но это не помогает, так как я хочу, чтобы было в группе форм. Я также пытался изменить workoutImageUrl, чтобы он совпадал с imgSrc из Firebase. Это работает, если я хочу чтобы показать текущее изображение тренировки, но оно не работает, когда я отправляю, потому что я получаю ошибку, что текущее изображение является нулевым.

Вот StackBlitz для этого проекта (немного упрощенно). Если вы щелкнете по тренировке в списке, вы можете выбрать «Управление тренировкой» и «Редактировать тренировку», чтобы перейти на страницу редактирования с заполненной формой (в настоящее время не работает с изображением). ge upload).

WorkoutEditComponent можно найти через src / app / features / workouts-page / workout-edit. Здесь вы можете увидеть логи c загрузки изображения, но я не думаю, что это имеет значение для этой конкретной проблемы c. Хранилище базы данных не работает на StackBlitz, но загрузка изображений работает (она просто не сохраняется). Я вставил пример API, чтобы это работало минимально для StackBlitz.

В WorkoutsListComponent отображается список отправленных тренировок.

Есть ли способ сохранить этот файл изображения тренировки, когда я просматриваю его во время редактирования разрабатывать? И в то же время не нужно ли повторно загружать изображение при редактировании формы? Я установил изображение для отображения внизу страницы редактирования, но если оно отображается здесь, оно все равно не загружает повторно или не использует то же изображение с сервера. Мне придется каждый раз перезагружать изображение.

Пожалуйста, дайте мне знать, если есть что-то, что я могу объяснить или объяснить.

Ответы [ 2 ]

1 голос
/ 22 февраля 2020

Вам нужно заново создать файл объекта из 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, и он работает, я надеюсь, что это помогает. Удачи!

Еще один способ решения проблемы с сердцами - использовать это:

const proxyUrl = 'https://cors-anywhere.herokuapp.com/';
fetch(proxyUrl  + workoutImageUrl)
0 голосов
/ 28 февраля 2020

Я предлагаю создать функцию, которая возвращает 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...