DEV Community

loading...
Cover image for (Javascript) My learning journey: Web Component

(Javascript) My learning journey: Web Component

Eric The Coder
Businessman and blogger #Javascript, #Python and #PHP. My favorite frameworks are #Nextjs, #Laravel, and #Django. I am also a fan of #TailwindCSS
Updated on ・3 min read

If you want to miss nothing click follow and you are welcome to comments and discuss with me.

Without further ado here is a summary of my notes for today.

What is Web Component

It's a set for web platform API's that allow us to create a custom, reusable and encapsulated html tags use in web pages and web apps.

Web component do not required any special javascript libraries or framework.

Web component have 3 main building blocks:

  • Custom Element
  • Shadow DOM
  • HTML Templates

Custom Element:

Create custom HTML tags, custom class and lifecycle methods

// class inherits from HTMLElement
class customButton extends HTMLElement {
  ...
}

// To bind the new custom element
window.customElements.define('x-button', customButton)
Enter fullscreen mode Exit fullscreen mode

Lifecycle methods:

  • constructor(): Called when an instance of the element is created
  • connectedCallback(): Call every time when the element is inserted into DOM
  • disconnectedCallback(): Call every time the element is remove from the DOM
  • attributeChangedCallback(attributeName, oldValue, newValue): Call when an attribute is added, removed, updated or replaced

Shadow DOM:

  • Used for self-contained components
  • Encapsulate styles and markup
  • Create with element.attachShadow({mode:open})
  • Creates a "shadowRoot" that we can reference and interact with

HTMl Template:

  • Define the encapsulated markup of our web component
  • Template tag stores markup on page
  • Include both HTML and CSS in template
  • Use slots to add custom text

My first component

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Web Component</title>
</head>
<body>
    <panic-button></panic-button>
    <script src="panicButton.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

panicButton.js

class panicButton extends HTMLElement {
    constructor() {
        // Call HTMLElement constructor
        super()
        // Add some content to our component
        this.innerHTML = `Hello World`
    }
}

// Bind our component
window.customElements.define('panic-button', panicButton)
Enter fullscreen mode Exit fullscreen mode

My First Component... I guess I can do better :)
First Component

Add attribute
index.html

<panic-button message="Women and Children first"></panic-button>
Enter fullscreen mode Exit fullscreen mode

panicButton.js

class panicButton extends HTMLElement {
    constructor() {
        // Call HTMLElement constructor
        super()
        // use getAttribute to retrieved attribute
        this.innerHTML = `P A N I C - ${this.getAttribute('message')}`
    }
}

// Bind our component
window.customElements.define('panic-button', panicButton)
Enter fullscreen mode Exit fullscreen mode

Use ShadowRoot:

// Create the element with custom CSS and HTML
const template = document.createElement('template')
template.innerHTML = `
<style>
    button {
        color: white;
        background-color: red;
        font-size: 16px;
        padding: 12px;
    }
</style>
<div>
    <button></button>
</div>
`
// Create web component
class panicButton extends HTMLElement {
    constructor() {
        super()
        // Create the ShadowRoot
        this.attachShadow({mode: 'open'})
        // Add our component inside our ShadowRoot
        this.shadowRoot.appendChild(template.content.cloneNode(true))
        // Set attributes        
        this.shadowRoot.querySelector('button').innerText = `P A N I C : ${this.getAttribute('message')}`
    }
}

window.customElements.define('panic-button', panicButton)
Enter fullscreen mode Exit fullscreen mode

Launch index.html
Web Component

Use slot

<panic-button>Women and Children First</panic-button>
Enter fullscreen mode Exit fullscreen mode
// Add the <slot /> tag
const template = document.createElement('template')
template.innerHTML = `
<style>
    button {
        color: white;
        background-color: red;
        font-size: 16px;
        padding: 12px;
    }
</style>
<div>
    <button><slot /></button>
</div>
`
Enter fullscreen mode Exit fullscreen mode

Multiple-slot

<panic-button>
  <div slot="message">General Alert</div>
  <div slot="image"><img src="alter.jpg"></div>
</panic-button>
Enter fullscreen mode Exit fullscreen mode
// Add the multiple slot tag by name
const template = document.createElement('template')
template.innerHTML = `
<style>
    button {
        color: white;
        background-color: red;
        font-size: 16px;
        padding: 12px;
    }
</style>
<div>
    <button>
        <slot name="message"/>
        <slot name="image"/>
    </button>
</div>
`
Enter fullscreen mode Exit fullscreen mode

Events

class panicButton extends HTMLElement {
    constructor() {
      ...
    }
    // Add the event listener inside this lifecycle hook
    connectedCallback() {
        this.shadowRoot.querySelector('button').addEventListener('click', e => {
            alert('This is not a exercice!')
        })
    }
  }
Enter fullscreen mode Exit fullscreen mode

Conclusion

That's it for today. If you want more info about web components you can read here: https://developer.mozilla.org/en-US/docs/Web/Web_Components

If you like what I write click follow to be alert when I publish a new post on Dev.to

Discussion (0)

Forem Open with the Forem app