鍋綿ブログ

C#・SharePoint・SharePoint Framework・Office365を中心に扱うブログです。

SharePoint FrameworkでWebパーツ同士を接続する方法 ~ 動的データ編 ~

以前弊ブログでグローバル変数を利用したWebパーツ接続の方法を紹介しましたが、SPFx v1.8 で動的データが一般提供となったため現在はこちらの利用が推奨となります。当記事では、できるだけシンプルに動的データ接続のやり方をご紹介します。

 

以前の記事はこちら

www.micknabewata.com

 

 

動的データを利用して何ができるか

SPFxで実装した2つのモジュール間で値の受け渡しができます。Webパーツ間に限らず、拡張機能とWebパーツの間などでもデータをやり取りすることが可能です。例えば・・

  • 検索ボックスWebパーツに入力された値に従って検索を行い、検索結果Webパーツに表示する
  • 住所一覧Webパーツで選択した住所を地図Webパーツで表示する

などの用途があります。

f:id:micknabewata:20190527113031p:plain

例:検索ボックスと検索結果

例えば上記の例では、検索ボックスWebパーツと検索結果Webパーツの2つを開発しています。

検索ボックスWebパーツが動的データを生成し、テキストボックスへの入力値を公開しています。検索結果Webパーツは動的データを受け取り、入力値に従ってSharePoint内を検索して表示しています。

入力値の受け渡しはインタラクティブに行われ、画面全体を更新することなく検索結果Webパーツの中身だけが再読み込みされるという挙動になります。

実装方法

テキストボックスへの入力値を表示するだけの非常にシンプルな例をGitHubに公開しました。以下でポイントを解説します。

github.com

動的データを保持するクラスの作成

はじめに、動的データの値を保持するクラスが必要です。Microsoft DocsのサンプルにあるようにWebパーツ自身がこの役割を担うことも可能ですが、コードの可読性という意味ではクラスを分けたほうが良いでしょう。

動的データの値を保持するクラスでは、IDynamicDataCallablesインタフェースを実装する必要があります。getPropertyDefinitionsメソッドでプロパティのデータ型を定義し、getPropertyValueメソッドで動的データの値を返却します。

SampleStringData.ts

import
{ IDynamicDataPropertyDefinition, IDynamicDataCallables } from '@microsoft/sp-dynamic-data'; /** プロパティID */ export const propertyId = 'sampleStringData'; /** 文字列型の値を公開する動的データクラスのサンプル */ export default class SampleStringData implements IDynamicDataCallables { /** 動的データの値を保持するプロパティ */ private _value : string; /** 動的データの型定義 */ public getPropertyDefinitions(): ReadonlyArray<IDynamicDataPropertyDefinition> { return [ { id: propertyId, title: 'サンプル文字列型データ' } ]; } /** 動的データの値を取得 */ public getPropertyValue(propId: string): string { switch (propId) { case propertyId: return this._value; } throw new Error('プロパティIDが不正です。'); } /** 動的データの値をセット */ public setPropertyValue(value : string) { this._value = value; } }

動的データを提供するWebパーツの作成

動的データを生成し、公開するWebパーツでは、前述のSampleStringDataクラスのインスタンスを保持し、値のセットとプロパティの更新を行います。動的データの初期化時にthis.context.dynamicDataSourceManager.initializeSourceメソッドを実行し、動的データの更新を行う際はthis.context.dynamicDataSourceManager.notifyPropertyChangedメソッドを実行します。

DataProviderWebPart.ts

import
* as React from 'react'; import * as ReactDom from 'react-dom'; import { Version } from '@microsoft/sp-core-library'; import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base'; import { IPropertyPaneConfiguration } from '@microsoft/sp-property-pane'; import * as strings from 'DataProviderWebPartStrings'; import DataProvider from './components/DataProvider'; import { IDataProviderProps } from './components/IDataProviderProps'; import SampleStringData, { propertyId } from '../../dynamicData/SampleStringData'; /** 動的データ生成Webパーツ プロパティ定義 */ export interface IDataProviderWebPartProps { } /** 動的データ生成Webパーツ */ export default class DataProviderWebPart extends BaseClientSideWebPart<IDataProviderWebPartProps> { /** 動的データクラス保持用 */ private sampleStringData : SampleStringData; /** 描画 */ public render(): void { const element: React.ReactElement<IDataProviderProps > = React.createElement( DataProvider, { stringInputCallBack : this.onStringSearch, addressInputCallBack : () => {}, phoneNumberInputCallBack : () => {} } ); ReactDom.render(element, this.domElement); } /** 文字列検索イベント */ private onStringSearch = (value : string) => { this.sampleStringData.setPropertyValue(value); this.context.dynamicDataSourceManager.notifyPropertyChanged(propertyId); } /** Webパーツ初期化イベント */ protected onInit(): Promise<void> { // 動的データ初期化 this.sampleStringData = new SampleStringData(); this.context.dynamicDataSourceManager.initializeSource(this.sampleStringData); // 初期化終了 return Promise.resolve(); } /** 破棄イベント */ protected onDispose(): void { ReactDom.unmountComponentAtNode(this.domElement); } /** データバージョン取得 */ protected get dataVersion(): Version { return Version.parse('1.0'); } /** プロパティ定義 */ protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration { return { pages: [ ] }; } }

動的データを利用するWebパーツの作成

公開されている動的データを利用するには、動的データの選択を行うためにWebパーツのプロパティを構成する必要があります。Webパーツのプロパティ名をプロパティウィンドウ定義の設定値と一致させる必要があることに注意してください。

DataViewerWebPart.ts

import
* as React from 'react'; import * as ReactDom from 'react-dom'; import { Version } from '@microsoft/sp-core-library'; import { BaseClientSideWebPart, PropertyPaneDynamicFieldSet, PropertyPaneDynamicField, DynamicDataSharedDepth, IWebPartPropertiesMetadata } from '@microsoft/sp-webpart-base'; import { IPropertyPaneConfiguration } from '@microsoft/sp-property-pane'; import * as strings from 'DataViewerWebPartStrings'; import DataViewer from './components/DataViewer'; import { IDataViewerProps } from './components/IDataViewerProps'; import { DynamicProperty } from '@microsoft/sp-component-base'; import { propertyId } from '../../dynamicData/SampleStringData'; /** 動的データ表示Webパーツ プロパティ定義 */ export interface IDataViewerWebPartProps { /** サンプル文字列 プロパティ名を プロパティウィンドウの定義と一致させること */ sampleStringData : DynamicProperty<string>; } /** 動的データ表示Webパーツ */ export default class DataViewerWebPart extends BaseClientSideWebPart<IDataViewerWebPartProps> { /** 描画 */ public render(): void { // 動的データ取得 let dString : string = (this.properties.sampleStringData)? this.properties.sampleStringData.tryGetValue() : undefined; // 要素の生成 const element: React.ReactElement<IDataViewerProps > = React.createElement( DataViewer, { string : dString } ); // 描画 ReactDom.render(element, this.domElement); } /** 破棄イベント */ protected onDispose(): void { ReactDom.unmountComponentAtNode(this.domElement); } /** データバージョン取得 */ protected get dataVersion(): Version { return Version.parse('1.0'); } /** プロパティウィンドウの構成 */ protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration { return { pages: [ { groups: [ { groupName : '動的データ接続', groupFields : [ PropertyPaneDynamicFieldSet({ label : '動的データ接続', fields : [ PropertyPaneDynamicField( propertyId, { label : '接続先' } ) ], sharedConfiguration : { depth : DynamicDataSharedDepth.Property } }) ] } ] } ] }; } }

 

以上、参考になれば幸いです。