React and JS Web Component - onChange Event Gets Lost when Cloning HTML from Template to Component Output

63 views Asked by At

I have a React app and I want to use a reusable JS web component that is supposed to output a <dialog> with content cloned from HTML inserted into the <custom-tag> of same JS component.

The HTML I want to clone has an <input type="file"> with an `onChange' event.

Once the JS component renders the <dialog> with the cloned HTML the onChange event gets lost and nothing happens as expected.

I'm looking for a way to NOT loose any of the events on any inputs and/or buttons passed on to the JS component.

I will provide code samples and a link to a GitHub repo.

https://github.com/ChidoYo/dialog-component.git

App.tsx

import React from 'react';
import './App.css';
import './webComponent/dialog_component'

declare global {
  namespace JSX {
    interface IntrinsicElements {
      "dialog-component": DialogComponentProps;
    }
  }
}

interface DialogComponentProps
  extends React.DetailedHTMLProps<
    React.HTMLAttributes<HTMLElement>,
    HTMLElement
  > {
  trigger: string;
  target: string;
}

function App() {
  return (
    <div>
      <h1>¡Hola!</h1>

      <div className='sample'>
        <p>Plain File Input</p>
        Upload
        <input
          type="file"
          id="plain"
          className='input-file'
          onChange={() => console.log('Outside Dialog')}
          accept="image/jpeg, image/png"
        />
      </div>

      <button className="btn-open" id="openDialog">Open Modal</button>

      <dialog-component id="dialogSample" trigger="openDialog" target="myDialog">
        <div>
          <p>File Upload in Dialog</p>
          <label htmlFor="outter-one" className='input-label'>
            Upload Picture
            <input
              type="file"
              id="outter-one"
              className='input-file'
              accept="image/jpeg, image/png"
              onChange={() => console.log('Inside Component')}
            />
          </label>          
        </div>
      </dialog-component>
    </div>
  );
}

export default App;

JS Web Component

class DialogComponent extends HTMLElement {

  connectedCallback() {

    const id = this.getAttribute('id')
    const trigger = this.getAttribute('trigger')
    const target = this.getAttribute('target')

    let dialogChildren = document.getElementById(id).firstChild.cloneNode(true)
    dialogChildren = dialogChildren.innerHTML

    console.log('dialogChildren', dialogChildren);

    const dialogContent = `
      <dialog id="${target}">
        <span class="icon"></span>
        <div class="text-content">
          ${dialogChildren}
        </div>
        <button class="btn-close" close-dialog autofocus>Close Modal</button>
      </dialog>
    `

    this.innerHTML = dialogContent

    // Open Dialog
    const openButton = document.getElementById(trigger)
    const closeButton = this.querySelector('[close-dialog]')
    const dialog = this.querySelector(`#${target}`)

    openButton.addEventListener('click', e => {
      e.preventDefault()      
      dialog.showModal()
    })

    closeButton.addEventListener('click', () => dialog.close())
  }
}

customElements.define('dialog-component', DialogComponent)
0

There are 0 answers