LoginSignup
0
0

CustoElementsで同じ名前のSlotを何度も利用したい

Last updated at Posted at 2023-07-27

はじめに

WebComponentsを作っているとShadowDom側にデザイン要素を持たないように作ると思います
そんな中で利用するslotで困ったことがあったのでまとめます

問題

WebComponentsでslotを何度も使いまわしたいと考えました

inde.html
<SampleElement>
  <div slot="test-msg">Hello</slot>
</SmapleElement>
index.tsx
return (
  <div>
    <slot name="test-msg"></slot>
    <slot name="test-msg"></slot>
    <slot name="test-msg"></slot>
  </div>
)

しかしこのときにHelloが表示されるのは最初のスロットのみでした
すべて表示させるにはどうすればよいのでしょうか?

原因

slotでは同じものをCustomElement側で何度もしようすることはできません
slot名を別名にしてhtmlにかけば利用することができます

index.html
<SampleElement>
  <div slot="test-msg-0">Hello</slot>
  <div slot="test-msg-1">Hello</slot>
  <div slot="test-msg-2">Hello</slot>
</SmapleElement>
index.tsx
return (
  <div>
    <slot name="test-msg-0"></slot>
    <slot name="test-msg-1"></slot>
    <slot name="test-msg-2"></slot>
  </div>
)

また、slotを同じ名前にすると最初にヒットした位置にすべてのスロットが表示されてしまいます

index.html
<SampleElement>
  <div slot="test-msg">Hello</slot>
  <div slot="test-msg">Hello</slot>
  <div slot="test-msg">Hello</slot>
</SmapleElement>
index.tsx
return (
  <div>
    <slot name="test-msg"></slot>
    <slot name="test-msg"></slot>
    <slot name="test-msg"></slot>
  </div>
)

このようにすると画面にはHelloHelloHelloと1つ目のスロット位置にでます

解決方法

この仕様を考えるとSlotのノードをクローンして使うほうが良いのかなと思い以下のように行いました

index.html
  <body>
    <script src="./src/index.tsx" type="module"></script>
    <div>
      <sample-element></sample-element>
    </div>
    <script>
      const sampleTag = document.getElementsByTagName("sample-element")[0];
      Array.from(new Array(5)).map((v, i) => {
        divElement = document.createElement("div")
        divElement.setAttribute("slot", `test-msg-${i}`)
        divElement.innerHTML = "Hello"
        sampleTag.appendChild(divElement)
      });
    </script>
  </body>
index.tsx
  return (
    <>
      <div>Hello</div>
      {Array.from(new Array(3)).map((v, i) => {
        return <slot name={`test-msg-${i}`}></slot>;
      })}
    </>
  );

手動でHTMLにSlotを3行書いてもよいですが、拡張性を考えてスクリプトで行いまいした
すこし強引ではありますが、これが考えた中では良いのかなと思います

おわりに

もっといい方法がある方はぜひとも教えてほしいです
WebComponent難しいなと改めて感じました

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0