Event listener not being triggered

62 views Asked by At

I'm trying to dispatch a custom event when an XMLHTTPRequest completes, and have a listener capture it and initiate the next action. However, the event listener is not being triggered as expected. I tested the same event listener by adding it to window and it works, but not when the event listener is added in a hook as shown below. What am I doing wrong?

Uploaders.Cloudinary_Direct = function(entries, onViewError) {
  entries.forEach(entry => {
    let formData = new FormData()
    let {
      url,
      fields
    } = entry.meta

    Object.entries(fields).forEach(([key, val]) => formData.append(key, val))
    formData.append("file", entry.file)
    formData.append("upload_preset", "avatar_upload");
    let xhr = new XMLHttpRequest()
    onViewError(() => xhr.abort())
    xhr.onload = () => {
      if (xhr.status === 204) {
        entry.progress(100)
      } else {
        entry.error()
      }
    }
    xhr.onerror = () => entry.error()
    xhr.onreadystatechange = function() {
      if (xhr.readyState == XMLHttpRequest.DONE) {

        console.log("public_id")
        let event = new CustomEvent("cloudinary_external_upload", {
          bubbles: true,
          cancelable: true,
          detail: {
            public_id: get_public_id(xhr)
          }
        });
        this.dispatchEvent(event); // also tried window.dispatchEvent.. in vain
      }
    }
    xhr.upload.addEventListener("progress", (event) => {
      if (event.lengthComputable) {
        let percent = Math.round((event.loaded / event.total) * 100)
        if (percent < 100) {
          entry.progress(percent)
        } else {
          entry.progress(100)
        }
      }
    })

    xhr.open("POST", url, true)
    xhr.send(formData)
  })
}

Hooks.ExternalUpload = {
  mounted() { // <-- This ensures the listener is add only after the component is mounted.
    this.el.addEventListener('cloudinary_external_upload', e => {
      console.log("cloudinary_upload") // <-- This is never printed.

      this.pushEvent("external_upload", {
        id: this.el.id,
        public_id: e.originalEvent.detail.public_id
      });
    });
  }
}

let liveSocket = new LiveSocket("/live", Socket, {
  hooks: Hooks,
  uploaders: Uploaders
})

EDIT: The debug inspector shows the event listener is properly added to the HTML element. event listener added to element

3

There are 3 answers

3
boradotri On

There might be a couple of issues causing your event listener not to trigger as expected: Here's how you can refactor your code to address these issues:

    Hooks.ExternalUpload = {
  mounted() {
    const el = this.el; // Capture the correct scope
    
    const cloudinaryUploadHandler = function(e) {
      console.log("cloudinary_upload");
      this.pushEvent("external_upload", { id: el.id, public_id: e.detail.public_id });
    };

    this.el.addEventListener('cloudinary_external_upload', cloudinaryUploadHandler.bind(this)); // Bind the correct scope

    // Clean up event listener when the hook is destroyed
    this.handleEvent("disconnect", () => {
      this.el.removeEventListener('cloudinary_external_upload', cloudinaryUploadHandler);
    });
  }
}
6
passThru On

For starters, looking at your custom event...

xhr.onreadystatechange = function() {

  if (xhr.readyState == XMLHttpRequest.DONE) {
      
      console.log("public_id")

      let event = new CustomEvent("cloudinary_external_upload", {bubbles: true,  cancelable: true, 

        detail: {

            public_id: get_public_id(xhr)
        } 
  });

    this.dispatchEvent(event);

Why are you dispatching outside of the readystate condition? I would place it inside like so...

xhr.onreadystatechange = function() {

  if (xhr.readyState == XMLHttpRequest.DONE) {
      
  console.log("public_id")

  let event = new CustomEvent("cloudinary_external_upload", {bubbles: true,  cancelable: true, 

    detail: {

        public_id: get_public_id(xhr)
    } 

this.dispatchEvent(event);

  });

If left outside you're dispatching when the custom event doesn't even exist yet.

Excuse the mess... FF is really playing up tonight... or maybe SO has a bug.

0
Jason O. On

The event listener had to be added to window instead of this.el.

Hooks.ExternalUpload = {
  mounted(){ 
    // window instead of this.el
    window.addEventListener('cloudinary_external_upload', e => {

     this.pushEvent("external_upload", {id: this.el.id, public_id: e.detail.public_id});
    });
  }
}