Прямая загрузка активного хранилища удаляет ввод файла во время загрузки с простой формой — Rails 6

#javascript #ruby-on-rails #ruby #rails-activestorage

#javascript #ruby-on-rails #ruby #rails-activestorage

Вопрос:

Мне удалось получить прямые загрузки, работающие с simple_form gem, используя вспомогательный метод параметров ввода. Проблема, с которой я сталкиваюсь, заключается в том, что запуск прямой загрузки приведет к отображению индикатора выполнения вместо ввода файла, и я не могу повторно загрузить другой файл, если к этому файловому вводу прикреплен неправильный файл. По сути, я пытаюсь заменить файлы, которые могли быть загружены — после факта. Как я могу запретить прямой загрузке заменять ввод файла индикатором выполнения?

direct_upload_file_input.rb

 class DirectUploadFileInput < SimpleForm::Inputs::FileInput 
 def input_html_options
  super.merge({direct_upload: true})
 end 
end
 

_form.html.erb

 has_one :media_file

  <%= f.input :media_file, as: :file, input_html: {:onchange => "activate_progress_bar", direct_upload: true}, label: false %>
 

direct_upload.js

// direct_uploads.js

 addEventListener("direct-upload:initialize", event => {
  const { target, detail } = event
  const { id, file } = detail
  target.insertAdjacentHTML("beforebegin", `
    <div id="direct-upload-${id}" class="direct-upload direct-upload--pending">
      <div id="direct-upload-progress-${id}" class="direct-upload__progress" style="width: 0%"></div>
      <span class="direct-upload__filename"></span>
    </div>
  `)
  target.previousElementSibling.querySelector(`.direct-upload__filename`).textContent = file.name
})

addEventListener("direct-upload:start", event => {
  const { id } = event.detail
  const element = document.getElementById(`direct-upload-${id}`)
  element.classList.remove("direct-upload--pending")
})

addEventListener("direct-upload:progress", event => {
  const { id, progress } = event.detail
  const progressElement = document.getElementById(`direct-upload-progress-${id}`)
  progressElement.style.width = `${progress}%`
})

addEventListener("direct-upload:error", event => {
  event.preventDefault()
  const { id, error } = event.detail
  const element = document.getElementById(`direct-upload-${id}`)
  element.classList.add("direct-upload--error")
  element.setAttribute("title", error)
})

addEventListener("direct-upload:end", event => {
  const { id } = event.detail
  const element = document.getElementById(`direct-upload-${id}`)
  element.classList.add("direct-upload--complete")
})
 

Ответ №1:

В вашем direct-upload:initialize методе вы заменяете target на индикатор выполнения div. target В этом случае устанавливается event.target значение, которое является вашим полем ввода файла. Вам нужно заменить или вставить индикатор выполнения в другой элемент страницы, если вы хотите сохранить ввод файла, но также отображать индикатор выполнения. Что-то вроде…

 let progress = document.getElementById('progress');
progress.innerHTML =
  `<div id="direct-upload-${id}" class="direct-upload direct-upload--pending">
    <div id="direct-upload-progress-${id}" class="direct-upload__progress" style="width: 0%"></div>
    <span class="direct-upload__filename"></span>
  </div>`