【SharePoint Online】リストアイテムをアコーディオンリンクで表示する ーSPFx開発 その7ー

2021年12月13日

こんにちは。
今回はとうとう自作のWebパーツを作成していきます。
業務でほしいなぁと思うアコーディオンリンク用のWebパーツを作成します。
せっかくなのでリストアイテムをリンクにするようなWebパーツにしていこうと思います。
今回編集したファイルはgithubに挙げておきます。
⇒既定値から編集していないファイルは上げていません。

それでは行きましょう。

注意事項

この記事は今までの記事の続きになります。
以下の記事一覧のその1(もしくはその0)から読んでいただくことを推奨いたします。
SharePoint Frameworkの記事一覧

accordion-link\src\webparts\accordionAccordionWebPart.ts

前回の記事で説明したとおり、Webパーツの根幹となるファイルです。
どのように修正していったかを説明していきます。

Import & Export

// jQuery関連ファイル
import * as jQuery from 'jquery';
import 'jqueryui';
// 外部CSSの読み込み
import { SPComponentLoader } from '@microsoft/sp-loader';

export interface IAccordionWebPartProps {
  description: string,
  listTitle: string;
}
// リストモデル
export interface ISPLists {
  value: ISPList[];
}

// 定義したリストモデルのプロパティを定義
export interface ISPList {
  Title: string;
  Url: string;
  DispName: string;
}
// HTTPClient読み込み
import {
  SPHttpClient,
  SPHttpClientResponse,
} from '@microsoft/sp-http';
import { List } from 'lodash';

今回はjQueryUIを利用してアコーディオンを生成しますので、まずjQueryとjQueryUIを読み込んでいます。
その他にSharePointからリスト情報を取得してくる必要があるため、リストモデルを定義しています。
この定義がないと、リストアイテムの列情報を取得できません。
今回取得する列は、[Title], [Url], [DispName] という内部名を持つ列ですのでそのように定義します。

また、SharePointと通信するためにHttpClientを読み込んでいます。

メインClass

メインのクラスを定義していきます。
セクションごとに説明していきます。

コンストラクタ

  //  jQueryUI スタイルを読み込み
  public constructor() {
    super();
    SPComponentLoader.loadCss('//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css');
  }

このコンストラクタでは、jQueryUIのスタイルを読み込んでいます。
それだけです。

リスト情報を取得するメソッド

  // リスト情報取得
  private _getListData(): Promise<ISPLists> {
    return this.context.spHttpClient.get(this.context.pageContext.web.absoluteUrl + `/_api/web/lists/GetByTitle('${this.properties.listTitle}')/Items`, SPHttpClient.configurations.v1)
      .then((response: SPHttpClientResponse) => {
        return response.json();
      })
      .then(jsonResponse => {
        console.log(jsonResponse.value);
        return jsonResponse;
      }) as Promise<ISPLists>;
  }

HttpClientを利用して、SharePointAPIでリストアイテムを取得しています。

[this.context.pageContext.web.absoluteUrl]
 ⇒ Webパーツを配置しているカレントサイトのURL
[/_api/web/lists/GetByTitle(‘${this.properties.listTitle}’)/Items]
 ⇒ リストアイテムを取得するためのAPI

最後に取得してきたjsonを返します。

表示するHTMLを構成するためのメソッド

  // spListContainerIDにHTMLを入れ込む
  private _renderList(items: ISPList[]): void {
    let html: string = '';
    let count: number = 0;
    html += `<div class="accordion">`
    items.forEach((item: ISPList) => {
      console.log(item.Title + " " + item.DispName);
      // もし表示名が登録されていなければカテゴリと判断
      if(item.DispName == null){
        console.log(count);
        if(count == 0){
          html += `
          <h3>${item.Title}</h3>
          <div>`
          count ++;
        }else{
          html += `
          </div>
          <h3>${item.Title}</h3>
          <div>`
        }
      }else{
        html += `
          <span class="${ styles.accordionItem }">
            <a href="${item.Url}">${item.DispName}</a></br>
          </span>`
      }
    });
    html += `</div></div>`;
    const listContainer: Element = this.domElement.querySelector('#spListContainer');
    listContainer.innerHTML = html;
    
    // jQuery UI アコーディオンのカスタムプロパティ
    const accordionOptions: JQueryUI.AccordionOptions = {
      animate: true,
      collapsible: false,
      icons: {
        header: 'ui-icon-circle-arrow-e',
        activeHeader: 'ui-icon-circle-arrow-s'
      }
    };

    // 初期化
    jQuery('.accordion', this.domElement).accordion(accordionOptions);
  }

このメソッドを呼び出す際に渡されたリストアイテムの情報を1つずつ処理してHTMLを生成しています。
最後に’#spListContainer’IDを持つHTMLに生成したHTMLをInsertしてあげています。

jQuery UI アコーディオンのカスタムプロパティは色々あるようなので興味があれば確認してみてください。

メソッドをまとめて順番に処理するためのメソッド

  private _renderListAsync(): void {
    // リストデータ取得
    this._getListData()
    .then((response) => {
      // リストレンダリング
      this._renderList(response.value);
    });
  }

上記で作成してきたメソッドを順番に処理しています。

レンダーメソッド

public render(): void {
    this.domElement.innerHTML = `
      <div id="spListContainer" />
    `;
      this._renderListAsync();
  }

  protected get dataVersion(): Version {
    return Version.parse('1.0');
  }

‘#spListContainer’IDを持つブロックを生成します。
その後、_renderListAsync()メソッドを実行し、Webパーツの表示を構成します。
上記メソッドで一番最初に処理されるメソッドです。

プロパティウィンドウを構成する

protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
    return {
      pages: [
        {
          header: {
            description: strings.PropertyPaneDescription
          },
          groups: [
            {
              groupName: strings.BasicGroupName,
              groupFields: [
                PropertyPaneTextField('description', {
                  label: strings.DescriptionFieldLabel
                }),
                PropertyPaneTextField('listTitle', {
                  label: 'listTitle'
                })
              ]
            }
          ]
        }
      ]
    };
  }

プロパティウィンドウを定義するメソッドです。
今回は対象のリストタイトルだけ設定され利用します。

accordion-link\src\webparts\AccordionWebPart.module.scss

Webパーツのスタイルを設定します。
今回はjQueryUIを利用しているため、ほとんどスタイルを変更することはありません。
追加分のみ説明します。

取得してきたアイテムのスタイル

.accordionItem{
  border-bottom: 1px solid #aaaaaa;
  display: inline-block;
  width: -webkit-fill-available;
  margin-bottom: 3px;
  
}

今回は1つのカテゴリに対してアイテムがいくつか登録される想定ですので、
inline-blockにしてあげています。
また、widthはブロックいっぱいに広がるようにしています。

accordion-link\src\webparts\AccordionWebPart.manifest.json

このファイルではWebパーツの既定値や基本情報を定義することができます。
今回はWebパーツのアイコンと、プロパティの既定値を修正しました。
それ以外はいじりません。

{
  "$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
  "id": "f9a27fb1-0005-4982-a296-265d08d361bc",
  "alias": "AccordionWebPart",
  "componentType": "WebPart",

  // The "*" signifies that the version should be taken from the package.json
  "version": "*",
  "manifestVersion": 2,

  // If true, the component can only be installed on sites where Custom Script is allowed.
  // Components that allow authors to embed arbitrary script code should set this to true.
  // https://support.office.com/en-us/article/Turn-scripting-capabilities-on-or-off-1f2c515f-5d7e-448a-9fd7-835da935584f
  "requiresCustomScript": false,
  "supportedHosts": ["SharePointWebPart"],

  "preconfiguredEntries": [{
    "properties": {
      "description": "accordion",
      "listTitle": "test2"
    },
    "groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other
    "group": { "default": "Other" },
    "title": { "default": "accordionLink" },
    "description": { "default": "アコーディオン形式でリストを表示します。" },
    "officeFabricIconFontName": "Page",
    "iconImageUrl": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAKXCAYAAAB6yC4RA...(省略)
  }]
}

“preconfiguredEntries”
⇒Webパーツ自体のタイトル、説明、アイコンなどを定義しています。
“properties”:
⇒Webパーツの説明の既定値、listTitleプロパティの既定値を設定してあげています。
“iconImageUrl”
⇒Webパーツのアイコンを指定しています。
 今回はMicrosoftが用意したアイコンではないものを利用するので、
 画像をBase64に変換してそれを張り付けています。
 詳しくは「Web パーツ アイコンの構成」を確認してみてください。

accordion-link\config\config.json

このファイルはWebパーツのbundle情報が記載されています。

{
  "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
  "version": "2.0",
  "bundles": {
    "accordion-web-part": {
      "components": [
        {
          "entrypoint": "./lib/webparts/accordion/AccordionWebPart.js",
          "manifest": "./src/webparts/accordion/AccordionWebPart.manifest.json"
        }
      ]
    }
  },
  "externals": {
    "jquery":"node_modules/jquery/dist/jquery.min.js",
    "jqueryui":"node_modules/jqueryui/jquery-ui.min.js"
  },
  "localizedResources": {
    "AccordionWebPartStrings": "lib/webparts/accordion/loc/{locale}.js"
  }
}

jQuery と jQueryUIをexternalsとして登録してあげています。
プロジェクトを構築すると、jQuery と jQueryUI は既定の Web パーツのバンドルに組み込まれません。
⇒Webパーツのファイル サイズの増加を多少改善できます。

表示してみる

それではテスト環境で利用してみましょう。
[gulp serve]コマンドを実行しておいてください。

まずはリストですが、表示したい順番にアイテムを作成します。
[カテゴリ]列は内部名は[Title]です。
また、カテゴリとなるアイテムにはUrl、DispNameは入力しません。

そして対象サイトのワークベンチを開きます。
指定したアイコンでWebパーツがあります。

ページに挿入し、プロパティを先程作成したリストを参照するように設定してみます。
listTitleを対象リストのリスト名に変更します。

想定通りに表示できました。
アイテム達はすべてリンクとなっており、正常に飛ぶことができました。

終わりに

今回は初めての自作Webパーツで、分からないことが途方もなくあり、
作成まで2か月近くかかってしまいました。。。
ですが、今回作成して役割等を覚えられたので次回はもう少し短期間で実装できる気がします。

それではまた。



次:
 【SharePoint Online】作成したWebパーツをTeamsタブとして利用する ーSPFx開発 その8ー

SharePoint Frameworkの記事一覧