How to target more than one dom element with same class to mount a svelte component

Viewed 1733

There are 2 parts to the problem i am facing

  1. I am trying to mount a component on two divs with same class name but the svelte component is loaded on the first target element.
  2. When i append an element on a click of a button , Svelte component targetting it must be loaded.

I am trying to achieve these cause i am working on a SPA application where widgets are added on click of a button.

My index.html looks like

<script>
    function addTable() {
        var iDiv = document.createElement('div');
        iDiv.className = 'table';
        document.body.appendChild(iDiv);
    }
</script>

<body>
    <div class="table"></div>
    <div class="table"></div>
    <button onclick="addTable()">Add Table</button>
    <script src='bundle.js'></script>
</body>

And my main.js looks like

import App from './App.svelte';

const app = new App({
  target: document.querySelector('.table')
});

export default app;
1 Answers

I was able to achieve both the issues/problems i have reported above

  1. How to mount a components on 2 div's having same class

I achieved this by going over all the elements sharing the class and instantiating the app for that eg:

document.querySelectorAll(".svelte-container").forEach(element => {
    if (!element.hasChildNodes()) {
      new App({
        target: element
      });
    }
  });
  1. How to load a component when a new div is added/appended to the DOM I achieved this by using MutationObserver.
var callback = function(mutationsList, observer) {
  for (var mutation of mutationsList) {
    if (mutation.type == "childList") {
      if (mutation.target.querySelector(".svelte-table")) {
        init();
      }
    }
  }
};

My index.html file looks like

<script>
      function addButton() {
        var elem1 = document.createElement("div");
        elem1.className = "svelte-table";
        elem2 = document.createElement("div");
        elem2.className = "svelte-container";
        elem1.appendChild(elem2);
        document.body.appendChild(elem1);
      }
    </script>
  </head>

  <body>
    <div></div>
    <div class="svelte-table"><div class="svelte-container"></div></div>
    <div class="svelte-table"><div class="svelte-container"></div></div>

    <button onclick="addButton()">Click me</button>
  </body>
  <script src="bundle.js"></script>

My main.js looks like

import App from "./App.svelte";
function init() {
  document.querySelectorAll(".svelte-container").forEach(element => {
    if (!element.hasChildNodes()) {
      new App({
        target: element
      });
    }
  });
}

init();

var targetNode = document.querySelector("body");
var config = { attributes: false, childList: true, subtree: true };

var callback = function(mutationsList, observer) {
  for (var mutation of mutationsList) {
    if (mutation.type == "childList") {
      if (mutation.target.querySelector(".svelte-table")) {
        init();
      }
    }
  }
};

var observer = new MutationObserver(callback);

// Start observing the target node for configured mutations
observer.observe(targetNode, config);
Related