> For the complete documentation index, see [llms.txt](https://lochiwei.gitbook.io/web/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lochiwei.gitbook.io/web/component/template/slot/slotchange.md).

# \`slotchange\` event

{% tabs %}
{% tab title="📗 參考" %}

* JS.info ⟩ [Updating slots](https://javascript.info/slots-composition#updating-slots)
* Google ⟩ [Working with slots in JS](https://developers.google.com/web/fundamentals/web-components/shadowdom#workwithslots)
  {% endtab %}

{% tab title="👉 相關" %}

* [Shadow DOM Events](/web/component/shadow-dom/events.md)
  {% endtab %}

{% tab title="📘 手冊" %}

* MDN ⟩ [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver)
* MDN ⟩&#x20;
  * HTMLSlotElement ⟩ [assignedNodes()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLSlotElement/assignedNodes): Node\[ ]
  * Element ⟩ [assignedSlot](https://developer.mozilla.org/en-US/docs/Web/API/Element/assignedSlot): HTMLSlotElement - slot that element is assigned to.
    {% endtab %}
    {% endtabs %}

{% hint style="info" %}
**Note:** "**slotchange"** does **not** fire when an instance of the component is first **initialized**.
{% endhint %}

The **`slotchange`** event fires when a slot's [distributed nodes](/web/component/template/slot/slotted-elements.md) changes. For example, if the user adds/removes children from the **light DOM**.

```javascript
const slot = this.shadowRoot.querySelector('#slot');

// ⭐️ `slotchange` event listener
slot.addEventListener('slotchange', e => {
    console.log('light dom children changed!');
});
```

{% hint style="info" %}
To monitor **other types** of changes to **light DOM**, you can setup a [`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) in your **element's constructor**.
{% endhint %}

## example

:floppy\_disk: [replit](https://replit.com/@pegasusroe/slotchange-event#CustomMenu.js)

{% tabs %}
{% tab title="CustomMenu.js" %}

```javascript
const { log } = console;

// CustomMenu
class CustomMenu extends HTMLElement {

    // connected to doc
    connectedCallback() {

        // shadow root
        const root = this.attachShadow({mode: 'open'});

        // shadow dom tree (with named slots ⭐️)
        root.innerHTML = `
        <div class="container">
            <slot name="title"></slot>
            <ul><slot name="item"></slot></ul>
        </div>
        `;

        // container (div.container)
        this.container = this.shadowRoot.firstElementChild;

        // ⭐️ shadowRoot can't have event handlers, 
        //    so using the first child.
        this.container.addEventListener('slotchange', e => {
            let slot = e.target;                // changed slot (in shadow DOM)
            log("slotchange: " + slot.name)     // ⭐️ slot name
            if(slot.name === 'item'){
                // ⭐️ slot.assignedElements() is of type `Element[]`
                let items = slot.assignedElements().map(elem => elem.textContent);
                log('items:', items);
            }
        });

    }// end: connectedCallback()

}// end: CustomMenu

// register <custom-menu> tag
customElements.define('custom-menu', CustomMenu);
```

{% endtab %}

{% tab title="script.js" %}

```javascript
// ⭐️ elem.$('div')
Element.prototype.$ = function(selector){
    return this.querySelector(selector);
};

// add 3 new menu items every sec
['Lollipop', 'Apple', 'Milk Shake'].forEach((text, i) => {
    setTimeout(() => {
        customMenu.insertAdjacentHTML('beforeEnd', 
            `<li slot="item">${text}</li>`
        )
    }, 1000 + i * 1000);
})


// change menu title in 4s
setTimeout(() => {
    customMenu.$('[slot="title"]').innerHTML = "New menu ⭐️";
}, 4000);
```

{% endtab %}

{% tab title="html" %}

```markup
<custom-menu id="customMenu">
	<!-- ⭐️ light dom: slotted elements -->
	<span slot="title">Candy menu</span>
</custom-menu>
```

{% endtab %}

{% tab title="⭐️ `slotchange` events" %}

| slot name | notes                                                                    |
| --------- | ------------------------------------------------------------------------ |
| title     | **`<span slot="title">Candy menu</span>`** inserted into **title slot**. |
| item      | new **`<li slot="item">`** tag inserted into **item slot**.              |
| item      | new **`<li slot="item">`** tag inserted into **item slot**.              |
| item      | new **`<li slot="item">`** tag inserted into **item slot**.              |

{% hint style="danger" %}
there's **NO`slotchange`** event after 4 sec (on **modifying the content** of a **slotted element**). &#x20;
{% endhint %}

{% hint style="info" %}
If we’d like to **track** internal **modifications** of **light DOM** from JavaScript, use: [MutationObserver](https://javascript.info/mutation-observer).
{% endhint %}
{% endtab %}
{% endtabs %}
