DEV Community

John Peters
John Peters

Posted on • Updated on

Observed Attributes

Image description

We created a ColorSpan Web Component defined here; which allows us to change the background color based on setting an attribute. The default background color is yellow.

The HTML markup for the image above was:

<h2>
  The NFC North
</h2>
<a href="https://www.vikings.com/">
  <color-span bgc="Purple" >
    Vikings
  </color-span>
</a>, 
<a href="#">
  <color-span>
    Green Bay
  </color-span>
</a>
, and others...

Enter fullscreen mode Exit fullscreen mode

For the Vikings markup, we added this attribute:
<color-span bgc="Purple">

"bgc"=BackGroundColor

Observed Attributes

How did we get "bgc" to be defined as an attribute? The rule is to use a static getter method named: observedAttributes, like this:

static get observedAttributes() {
    return ["bgc"];
}
Enter fullscreen mode Exit fullscreen mode

This method returns an array of strings which define allowable attributes. In this case, just one string is returned ["bgc"].

<color-span bgc="Purple">
 Vikings
</color-span>

Enter fullscreen mode Exit fullscreen mode

The Attribute Changed CallBack

Because of the defined static getter function observedAttributes(), the WebComponent interface will call the attributeChangedCallback function when an attribute changes.

attributeChangedCallback(name, oldValue, newValue) {  
  this.SetStyle(name,newValue);
}

Enter fullscreen mode Exit fullscreen mode

SetStyle Function

SetStyle(name, color){
  //Defaults to Yellow
  let backgroundColor = "Yellow"; 
  if(color=="Purple"){
    backgroundColor="#C5B4E3";
  }
  this.style.textContent = `
  span:hover { text-decoration: underline; color:red; }            
  :host(.footer) { color : #555; }
  :host { background-color:${backgroundColor}; padding: 2px 5px; }
`;
}
Enter fullscreen mode Exit fullscreen mode

The Color Span WebComponent

//A Webcomponent based on a span with built ability to change background color
class ColorSpan extends HTMLElement {
  span = null;
  style = null;

  constructor() {
    super();

    this.span = document.createElement("span");
    this.span.textContent = this.textContent;
    this.style = document.createElement("style");
    this.SetStyle();

    let shadowRoot = this.attachShadow({ mode: "open" });
    this.shadowRoot.appendChild(this.style);
    shadowRoot.appendChild(this.span);
  }
  SetStyle(name, color) {
    let backgroundColor = "Yellow";
    if (color == "Purple") {
      backgroundColor = "#C5B4E3";
    }
    this.style.textContent = `
  span:hover { text-decoration: underline; color:red; }            
  :host(.footer) { color : #555; }
  :host { background-color:${backgroundColor}; padding: 2px 5px; }
`;
  }
  static get observedAttributes() {
    return ["bgc", "color"];
  }

  attributeChangedCallback(name, oldValue, newValue) {
    this.SetStyle(name, newValue);
  }
}

// Define the new element
customElements.define("color-span", ColorSpan);

Enter fullscreen mode Exit fullscreen mode

The HTML Head

The script tag brings in the component from the main.js file with the defer attribute.

  <head>
    <meta charset="utf-8">
    <title>Host selectors</title>
    <script src="main.js" defer></script>
    <link rel="stylesheet" href="styles.css">
  </head>
Enter fullscreen mode Exit fullscreen mode

Warning

Most purists would say this is a violation of concerns. And they would be right. We already have Styles, so why do this? The answer is to learn how a Web Component callback works.

Top comments (0)