tamuです。

lightning-accordion-sectionを試してみました。

動的にコンテンツを追加するやり方や、一気に開いたり閉じたりするやり方についてまとめました。

accordion-sectionとは

lightning-accordion で指定する、一セクションです。 lightning-accordion-section タグで囲われた中身がまとめて表示されたり非表示になったりします。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<lightning-accordion>
  <lightning-accordion-section name="section1" label="セクション1">
    <p>吾輩は猫である。名前はまだ無い。</p>
    <p>どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。この書生というのは時々我々を捕えて煮て食うという話である。しかしその当時は何という考もなかったから別段恐しいとも思わなかった。ただ彼の掌に載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。</p>
    <p>掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始であろう。この時妙なものだと思った感じが今でも残っている。第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶だ。その後猫にもだいぶ逢ったがこんな片輪には一度も出会わした事がない。のみならず顔の真中があまりに突起している。そうしてその穴の中から時々ぷうぷうと煙を吹く。どうも咽せぽくて実に弱った。これが人間の飲む煙草というものである事はようやくこの頃知った。</p>
  </lightning-accordion-section>
  <lightning-accordion-section name="section2" label="セクション2">
    <p>この書生の掌の裏でしばらくはよい心持に坐っておったが、しばらくすると非常な速力で運転し始めた。書生が動くのか自分だけが動くのか分らないが無暗に眼が廻る。胸が悪くなる。到底助からないと思っていると、どさりと音がして眼から火が出た。それまでは記憶しているがあとは何の事やらいくら考え出そうとしても分らない。</p>
    <p>ふと気が付いて見ると書生はいない。たくさんおった兄弟が一疋も見えぬ。肝心の母親さえ姿を隠してしまった。その上今までの所とは違って無暗に明るい。眼を明いていられぬくらいだ。はてな何でも容子がおかしいと、のそのそ這い出して見ると非常に痛い。吾輩は藁の上から急に笹原の中へ棄てられたのである。</p>
  </lightning-accordion-section>
</lightning-accordion>

これを表示するとこんな感じになります。

accordion-sectionのサンプル

動的にセクションを追加したい

こういうコンポーネントを使う際は、サーバからデータを持ってきてクライアント側で表示したい、みたいな要求があると思います。 そういった場合のやり方です。

表示するテンプレートはこんな感じです。

lightning-accordion の中でループを作って lightning-accordion-section を置いていきます。

lightning-accordion-sectionkey が必要なのでそこだけ注意が必要です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<template>
  <lightning-accordion>
      <template for:each={sections} for:item="sec">
        <lightning-accordion-section name={sec.name} label={sec.name} key={sec.name}>
            <ul>
                <template for:each={sec.works} for:item="work">
                    <li key={work}>{work}</li>
                </template>
            </ul>
        </lightning-accordion-section>
      </template>
  </lightning-accordion>
</template>

JSはこんな感じです。 わざわざ connectedCallback で内容を設定しているのは、 Apex等でサーバからレコードを取得してそれをセットしているのを模しているためです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import { LightningElement, api } from 'lwc';

export default class Accordionsection extends LightningElement {

  /** @type boolean */
  initialized = false

  @api
  sections = [];

  connectedCallback() {
    if (this.initialized) {
      return ;
    }
    this.initialized = true;
    this.sections = [
      {
        name: '1905',
        works: [
          '吾輩は猫である',
        ],
      },
      {
        name: '1906',
        works: [
          '坊っちゃん',
          '草枕',
          '二百十日',
        ]
      },
      {
        name: '1907',
        works: [
          '野分',
          '虞美人草'
        ]
      }
    ];
  }
}

これを実行するとこんな感じになります。

動的にセクションを追加した図その1 動的にセクションを追加した図その2

すべて展開

複数の lightning-accordion-section を一気に開きたい、一気に閉じたいというとき、 lightning-accordion 側を操作することで実現できます。

ポイントは active-section-name です。 これにセクション名をセットすることで開いたり閉じたりすることができます。

テンプレート側は Expand All ボタン、 Collapse All ボタンを追加しています。 また、 lightning-accordionallow-multiple-sections-open を追加しています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<template>
  <lightning-accordion allow-multiple-sections-open>
      <template for:each={sections} for:item="sec">
        <lightning-accordion-section name={sec.name} label={sec.name} key={sec.name}>
            <ul>
                <template for:each={sec.works} for:item="work">
                    <li key={work}>{work}</li>
                </template>
            </ul>
        </lightning-accordion-section>
      </template>
  </lightning-accordion>
  <lightning-button label="Expand All" onclick={handleExpandAll}></lightning-button>
  <lightning-button label="Collapse All" onclick={handleCollapseAll}></lightning-button>
</template>

JS側は Expand All 用のメソッドと Collapse All 用のメソッドを追加しています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import { LightningElement, api } from 'lwc';

export default class Accordionsection extends LightningElement {

  /** @type boolean */
  initialized = false

  @api
  sections = [];

  connectedCallback() {
    if (this.initialized) {
      return ;
    }
    this.initialized = true;
    this.sections = [
      {
        name: '1905',
        works: [
          '吾輩は猫である',
        ],
      },
      {
        name: '1906',
        works: [
          '坊っちゃん',
          '草枕',
          '二百十日',
        ]
      },
      {
        name: '1907',
        works: [
          '野分',
          '虞美人草'
        ]
      }
    ];
  }

  handleExpandAll() {
    var acc = this.template.querySelector('lightning-accordion');
    var sectionNames = []
    for (const sec of this.template.querySelectorAll('lightning-accordion-section')) {
      sectionNames.push(sec.name);
    }
    acc.activeSectionName = sectionNames;
  }

  handleCollapseAll() {
    this.template.querySelector('lightning-accordion').activeSectionName = [];
  }
}

Expand All

lightning-accordion のソースコードを見てみると、 active-section-namesetter を持っています。

そのためここにすべての lightning-accordion-section の名前をセットすれば開くことになります。

今回の Expand All メソッドではわざわざ lightning-accordion-section を検索してそこから name を持ってきていますが、 name はテンプレートにセットするタイミングで知っている値なのでインスタンスに持たせておくともっと効率的だと思います。

一気に開くとこうなります。

一気に開いた状態

Collapse All

一気に閉じるのは簡単です。 Expand All の逆で active-section-name に空の配列をセットしてあげれば閉じることになります。

一気に閉じた状態

速度について

ためしに lightning-accordion-section を100個用意して Expand AllCollapse All をやってみました。

結果、押した瞬間にすべてが展開されました。 意外と速いようです。

100個のセクションを一気に展開したときの図

参考元

Component Reference