skip to Main Content

I want to create an element on the fly with attributes, NOT add them after the object is already created (setAttribute does not work).

Point: I have setup a web component to interact with it’s attributes inside it’s constructor (this.getAttribute). If you create an element on the fly (document.createElement) the attributes are empty. Setting them afterwards won’t work.

note: I know I can get the funcality I need in another way, this would just create the most user friendly version of the web component (minimal code).

class List extends HTMLElement {
    constructor(temp) {
        super();
             if(this.getAttribute('att')!=null){
                 do stuff
             }
     }
 }

other code

document.createElement('list')

2

Answers


  1. here is a quick sample showing how to reference and set attributes within a web-component class definition.
    You can’t reference attributes from the constructor, I think this is actually a static method, not an instance method.

    connectedCallback() and likely? adoptedCallback will allow interaction with the element Object.

    This demonstrates testing for an attribute, setting an attribute and value, and getting a value.
    I use dataset https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset cause that is where custom values ideally should go.

    class UIInput extends HTMLElement {
      constructor() {
        super();
        // will cause issue if un commented
        console.log(`'data-testing' value is ${this.dataset.testing}`);
      };
    
      connectedCallback() {
        // empty signature
        // test for attribute
        if (!this.dataset.testing) {
          console.log(`'data-testing' attribute absent`);
          //print the element
          console.log(this);
          return;
        }
        // set / assign an attribute value
        this.dataset.connected = true;
        console.log(`'data-testing' value is ${this.dataset.testing} and 'connected' is ${this.dataset.connected}`);
        // print the element
        console.log(this);
    
      };
    };
    customElements.define('ui-input', UIInput);
    <ui-input id="empty">Empty!</ui-input>
    <br/>
    <ui-input id="supplied" data-testing="Value Supplied">Value Supplied</ui-input>
    Login or Signup to reply.
  2. Here is a playground showing when and when not attributes are available in the constructor

    https://jsfiddle.net/WebComponents/cxntaodk/

    Run the code, explain for yourself what the console shows

    <div id="container"></div>
    <script>
      class BaseClass extends HTMLElement {
        constructor() {
          super();
          console.log(this.nodeName, this.id||"NO ID", "constructor");
        }
        connectedCallback() {
          this.innerHTML = this.id;
        }
      }
      customElements.define("component-a", class extends BaseClass {});
      container.innerHTML += `<component-a id="1"></component-a><component-b id="2">Hello! Web Component</component-b>`;
    </script>
    <component-a id="3"></component-a><component-b id="4"></component-b>
    <script>
      customElements.define("component-b", class extends BaseClass {});
      container.innerHTML += `<component-a id="5"></component-a><component-b id="6">Hello! Web Component</component-b>`;
      const element = (tag, props = {}) => Object.assign(document.createElement(tag), props);
      document.body.append(
        element("component-a", {
          id: "7"
        }),
        element("component-b", {
          id: "8"
        })
      );
    </script>
    • the constructor only has access to attributes WHEN THE DOM WAS PARSED

    • setting innerHTML causes a DOM parse and sets all attributes (which I think OP is asking)

    • createElement only runs the constructor, does not parse DOM
      That is why the general advice is to not access attributes/DOM in the constructor

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search