Search code examples
vuejs3bootstrap-modal

How to activate bootstrap modal after selecting files in input in Vue 3?


So, I'm doing a chat component and we've the option to send files, but prior to send it the user must review it and for it i had the idea to show a modal containing all the files selected, but i just can't show the modal right after the file selection, i tried getElementById but it did not work.

Here's my template:

    <input type="file" multiple name="file" id="fileInput" class="hidden-input" @change="onChange"
       ref="file" accept=".pdf,.jpg,.jpeg,.png" hidden />
    <button type="button" @click="chooseFiles()" class="btn btn-link text-decoration-none emoji-btn"
       id="emoji-btn">
       <i class="las la-arrow-up align-middle" />
    </button>

And here's my script:

    chooseFiles() {
      document.getElementById("fileInput").click()
      // document.getElementById("showModal").click()
    },
    onChange(e) {
      this.$refs.file.files = e.target.files
      this.files.push(...this.$refs.file.files)
      this.fileSize(e)
      // document.getElementById("showModal").click()
    },

And here is the modal:

  <div id="showModal" class="modal fade" ref="modal" tabindex="-1" aria-labelledby="myModalLabel">
    <div class="modal-dialog modal-lg">
      <div class="modal-content">
        <div class="modal-body">
          <div v-for="file in files" :key="file.name" class="preview-card border rounded">
            <div class="d-flex align-items-center p-2">
              <b-img v-if="file.type != 'application/pdf'" class="img-thumbnail me-2" alt="200x200" width="200"
                :src="generateURL(file)" data-holder-rendered="true" />
              <iframe v-else class="img-thumbnail me-2" data-holder-rendered="true" frameBorder="0" scrolling="no"
                alt="200x200" width="200" :src="generateURL(file)" />
              <div class="flex-grow-1">
                <div class="pt-1">
                  <h5 class="fs-11 mb-1" data-dz-name="">
                    {{ file.name }}
                  </h5>
                  <p class="fs-9 text-muted mb-0" data-dz-size="">
                    <strong>{{ (file.size / 1024) / 1000 }}</strong> MB
                  </p>
                  <strong class="error text-danger" data-dz-errormessage="" />
                </div>
              </div>
            </div>
          </div>
        </div>
        <div class="modal-footer">
          <b-button type="button" class="btn btn-danger" data-bs-dismiss="modal">
            Sair
          </b-button>
        </div>
      </div>
    </div>
  </div>

Solution

  • When I was commenting I missed the fact this was tagged bootstrap-modal, so I understand now you're wanting to open a bootstrap modal which has a specific method for activation. For bootstrap 5 you can get the Modal instance with bootstrap.Modal.getOrCreateInstance(). Assign this to a data property and then you can call all the typical modal methods on it like .show(), .toggle(), .hide(), etc. Below is a working example using a more simplified modal than your own just for simplicity sake.

    <div id="app">
      <input type="file" multiple name="file" id="fileInput" class="hidden-input" @change="onChange"
             ref="file" accept=".pdf,.jpg,.jpeg,.png" hidden />
      <button type="button" @click="chooseFiles" class="btn btn-link text-decoration-none emoji-btn"
              id="emoji-btn">
        choose files
      </button>
      
      <!-- Modal -->
      <div class="modal fade" ref="modal" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
        <div class="modal-dialog">
          <div class="modal-content">
            <div class="modal-header">
              <h5 class="modal-title" id="exampleModalLabel">Files</h5>
              <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
              <div v-for="(file, i) in files" :key="i">
              {{ file.name }}
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    
      data() {
        return {
          files: [],
          modal: null
        }
      },
      mounted() {
        const myModalEl = this.$refs.modal
        this.modal = bootstrap.Modal.getOrCreateInstance(myModalEl)
      },
      methods: {
        chooseFiles() {
            this.$refs.file.click()
        },
        onChange(e) {
          this.$refs.file.files = e.target.files
          this.files.push(...this.$refs.file.files)
          this.modal.show()
        },
      }
    

    and here is the sandbox with the above code

    If bootstrap 5 is installed as a package you can do this instead:

    import { Modal } from "bootstrap";
    .
    .
    .
    mounted() {
      this.modal = new Modal(this.$refs.modal);
    }