(Javascript) My learning journey: Web Component
Tags: javascript, beginners, tutorial
Published: 2021-03-06 13:32:20

---
title: (Javascript) My learning journey: Web Component
description:
published: true
tags: javascript, beginner, tutorial
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ik1c8mr2sz8zi3g466dq.jpg
series: (Javascript) My learning journey
---

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.

<h2>What is Web Component</h2>
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

<h4>Custom Element:</h4>
Create custom HTML tags, custom class and lifecycle methods
```js
// class inherits from HTMLElement
class customButton extends HTMLElement {
  ...
}

// To bind the new custom element
window.customElements.define('x-button', customButton)
```

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

<h4>Shadow DOM:</h4>
- 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

<h4>HTMl Template:</h4>
- 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

<h2>My first component</h2>
index.html
```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>
```

panicButton.js
```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)
```
My First Component... I guess I can do better :)
![First Component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pkpiv5fwc7jdlhgiecxw.png)

Add attribute
index.html
```html
<panic-button message="Women and Children first"></panic-button>
```

panicButton.js
```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)
```

Use ShadowRoot:
```js
// 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)
```

Launch index.html
![Web Component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bv2bblk4uc308esvhvbw.png)

Use slot
```html
<panic-button>Women and Children First</panic-button>
```

```js
// 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>
`
```

Multiple-slot
```html
<panic-button>
  <div slot="message">General Alert</div>
  <div slot="image"><img src="alter.jpg"></div>
</panic-button>
```

```js
// 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>
`
```

Events
```js
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!')
        })
    }
  }
```

<h2>Conclusion</h2>
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