Skip to main content
Since Shoelace 2.0 Code stable

Mutation Observer

sl-mutation-observer

The Mutation Observer component offers a thin, declarative interface to the MutationObserver API.

Examples

Mutation Observer Basics

The mutation observer will report changes to the content it wraps through the sl-mutation event. When emitted, a collection of MutationRecord objects will be attached to event.detail that contains information about how it changed.

Click to mutate
👆 Click the button and watch the console
<div class="mutation-overview">
  <sl-mutation-observer attr="variant">
    <sl-button variant="primary">Click to mutate</sl-button>
  </sl-mutation-observer>

  <br />
  👆 Click the button and watch the console

  <script>
    const container = document.querySelector('.mutation-overview');
    const mutationObserver = container.querySelector('sl-mutation-observer');
    const button = container.querySelector('sl-button');
    const variants = ['primary', 'success', 'neutral', 'warning', 'danger'];
    let clicks = 0;

    // Change the button's variant attribute
    button.addEventListener('click', () => {
      clicks++;
      button.setAttribute('variant', variants[clicks % variants.length]);
    });

    // Log mutations
    mutationObserver.addEventListener('sl-mutation', event => {
      console.log(event.detail);
    });
  </script>

  <style>
    .mutation-overview sl-button {
      margin-bottom: 1rem;
    }
  </style>
</div>
.mutation-overview
  sl-mutation-observer attr="variant"
    sl-button variant="primary"
      | Click to mutate
  br
  |  👆 Click the button and watch the console

javascript:
  const container = document.querySelector('.mutation-overview');
  const mutationObserver = container.querySelector('sl-mutation-observer');
  const button = container.querySelector('sl-button');
  const variants = ['primary', 'success', 'neutral', 'warning', 'danger'];
  let clicks = 0;

  // Change the button's variant attribute
  button.addEventListener('click', () => {
    clicks++;
    button.setAttribute('variant', variants[clicks % variants.length]);
  });

  // Log mutations
  mutationObserver.addEventListener('sl-mutation', event => {
    console.log(event.detail);
  });

css:
  .mutation-overview sl-button {
    margin-bottom: 1rem;
  }

Child List

Use the child-list attribute to watch for new child elements that are added or removed.

Add button
👆 Add and remove buttons and watch the console
<div class="mutation-child-list">
  <sl-mutation-observer child-list>
    <div class="buttons">
      <sl-button variant="primary">Add button</sl-button>
    </div>
  </sl-mutation-observer>

  👆 Add and remove buttons and watch the console

  <script>
    const container = document.querySelector('.mutation-child-list');
    const mutationObserver = container.querySelector('sl-mutation-observer');
    const buttons = container.querySelector('.buttons');
    const button = container.querySelector('sl-button[variant="primary"]');
    let i = 0;

    // Add a button
    button.addEventListener('click', () => {
      const button = document.createElement('sl-button');
      button.textContent = ++i;
      buttons.append(button);
    });

    // Remove a button
    buttons.addEventListener('click', event => {
      const target = event.target.closest('sl-button:not([variant="primary"])');
      event.stopPropagation();

      if (target) {
        target.remove();
      }
    });

    // Log mutations
    mutationObserver.addEventListener('sl-mutation', event => {
      console.log(event.detail);
    });
  </script>

  <style>
    .mutation-child-list .buttons {
      display: flex;
      gap: 0.25rem;
      flex-wrap: wrap;
      margin-bottom: 1rem;
    }
  </style>
</div>
.mutation-child-list
  sl-mutation-observer child-list=true
    .buttons
      sl-button variant="primary"
        | Add button

javascript:
  const container = document.querySelector('.mutation-child-list');
  const mutationObserver = container.querySelector('sl-mutation-observer');
  const buttons = container.querySelector('.buttons');
  const button = container.querySelector('sl-button[variant="primary"]');
  let i = 0;

  // Add a button
  button.addEventListener('click', () => {
    const button = document.createElement('sl-button');
    button.textContent = ++i;
    buttons.append(button);
  });

  // Remove a button
  buttons.addEventListener('click', event => {
    const target = event.target.closest('sl-button:not([variant="primary"])');
    event.stopPropagation();

    if (target) {
      target.remove();
    }
  });

  // Log mutations
  mutationObserver.addEventListener('sl-mutation', event => {
    console.log(event.detail);
  });

css:
  .mutation-child-list .buttons {
    display: flex;
    gap: 0.25rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
  }

Component Props

Property Default Details
attr —

string

Watches for changes to attributes. To watch only specific attributes, separate them by a space, e.g. attr="class id title". To watch all attributes, use *.

attrOldValue
attr-old-value
false

boolean

Indicates whether or not the attribute’s previous value should be recorded when monitoring changes.

charData
char-data
false

boolean

Watches for changes to the character data contained within the node.

charDataOldValue
char-data-old-value
false

boolean

Indicates whether or not the previous value of the node’s text should be recorded.

childList
child-list
false

boolean

Watches for the addition or removal of new child nodes.

disabled false

boolean

Disables the observer.

updateComplete A read-only promise that resolves when the component has finished updating.

Learn more about attributes and properties.

Slots

Name Details
(default) The content to watch for mutations.

Learn more about using slots.

Events

Name Name Name React Event Details
sl-mutation sl-mutation sl-mutation onSlMutation

{ mutationList: MutationRecord[] }

Emitted when a mutation occurs.

Learn more about events.