Home > Blockchain >  Is there a way to add custom attributes to custom elements
Is there a way to add custom attributes to custom elements

Time:04-16

While messing around with custom elements I wondered if one could use custom attributes within the elements (and possibly within their children too). I know VueJS does something similar with attributes like v-bind, v-for, etc; and I know there's probably a lot more going on under the hood there than I realize. I've tried registering custom elements and attempting to retrieve them like so:

<new-element cool="Awesome!"> </new-element>

class NewElement extends HTMLElement {
    constructor() {
        super();
        this.coolAttr = this.getAttribute("cool");
    }
}

customElements.define("new-element", NewElement);

However, when loading the page (in Google Chrome for me) the "custom" attributes disappear, and any attempt at getting them retrieves null. Is there a way to "register" these custom attributes, or do I have to stick with data- attributes?

CodePudding user response:

  • Attributes become available in the connectedCallback,
    they are not available yet in the constructor
    Unless the Custom Element is PARSED (in the DOM) BEFORE the Element is defined!!

  • Also be aware the attributeChangedCallback runs before the connectedCallback
    for Observed attributes

  • Also see: https://andyogo.github.io/custom-element-reactions-diagram/

.as-console-row-code {
    font: 12px Arial!important;
    background:yellow;
    color:darkred;
}
.as-console-row:after{ display:none!important }
<before-element cool="Awesome?">FOO</before-element>

<script>
  class NewElement extends HTMLElement {
    log( ...args ){
      console.log(this.nodeName, `cool:${this.getAttribute("cool")}`,"\t\t\t",...args );
    }
    static get observedAttributes() {
      return ["cool"];
    }
    constructor() {
      const name = "constructor"; // CAN! run code BEFORE super()!
      // super() sets AND returns the 'this' scope
      super().log(name);
    }
    connectedCallback() {
      this.log("connectedCallback", this.innerHTML || "innerHTML not parsed yet");
      // be aware this.innerHTML is only available for PARSED elements
      // use setTimeout(()=>{...},0) if you do need this.innerHTML
    }
    attributeChangedCallback(name, oldValue, newValue) {
      this.log(`attributeChangedCallback name:${name}, old:${oldValue}, new:${newValue}`);
    }
  }
  customElements.define("before-element", class extends NewElement {});
  customElements.define("after-element",  class extends NewElement {});
</script>

<after-element cool="Awesome!!">BAR</after-element>

CodePudding user response:

It can be easily solved by adding the name of the attributes after "data-".

<New-element data-*="Anything you want" />

for example, you can have:

<element data-cool="value">

You can have as many custom attributes as you want.

  • Related