Search code examples
javascriptclassscopedeclarationweb-component

How to define global constant when creating Web component?


I am creating custom web component "upload-widget", and declaring three constants in constructor to be referenced in functions later:

const template = document.createElement('template');
template.innerHTML = `
  <div id="dropper-zone">
    <input type="file" name="file_input" id="file_name">
    <button type="button" id="upload_btn">Upload</button>
    <div id="upload_status"></div>
  </div>
  `;

class UploadWidget extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({mode: 'open'});
    this.shadowRoot.appendChild(template.content.cloneNode(true));

    const FILE_NAME = this.shadowRoot.getElementById("file_name");
    const UPLOAD_BUTTON = this.shadowRoot.getElementById("upload_btn");
    const UPLOAD_STATUS = this.shadowRoot.getElementById("upload_status");


  };

  upload_action() {
    if (!FILE_NAME.value) {
    console.log("File does not exists");
        return;
    UPLOAD_STATUS.innerHTML = 'File Uploaded';
  };

  connectedCallback() {
    UPLOAD_BUTTON.addEventListener("click", () => this.upload_action());
  }
}

customElements.define('upload-widget', UploadWidget);

This code fails since Javascript does not recognize the declared constants in the "connectedCallback()" nor in the function "upload_action()". Moving the declaration to either of the functions makes the constants valid only for the function scope, not beyond. How do I declare constant/variable valid for the whole scope of the class including functions?


Solution

  • you need to declare them as class variables, so your constructor would look like:

    constructor() {
        super();
        this.attachShadow({mode: 'open'});
        this.shadowRoot.appendChild(template.content.cloneNode(true));
    
        this.FILE_NAME = this.shadowRoot.getElementById("file_name");
        this.UPLOAD_BUTTON = this.shadowRoot.getElementById("upload_btn");
        this.UPLOAD_STATUS = this.shadowRoot.getElementById("upload_status");
      };
    

    Later in the code you can access them as this.UPLOAD_BUTTON.

    Advice: Try to use camelCase when naming variables, it looks more "javascripty". So instead of this.UPLOAD_BUTTON write this.uploadButton.