動的データを使用した、SharePoint Framework コンポーネントの接続Connect SharePoint Framework components using dynamic data

動的データ機能を使用して、SharePoint Framework のクライアント側 web パーツと拡張機能を相互に接続し、コンポーネント間で情報を交換できます。Using the dynamic data capability, you can connect SharePoint Framework client-side web parts and extensions to each other and exchange information between the components. これにより、リッチ エクスペリエンスと魅力的なエンドユーザー向けのソリューションを構築することができます。This allows you to build rich experiences and compelling end-user solutions.

イベントに関する情報を表示する、相互に接続されている SharePoint Framework の 3 つの web パーツ

動的データ ソースを使用したデータの公開Expose data using dynamic data source

SharePoint Framework の動的データは、ソース通知モデルに基づいています。Dynamic data in the SharePoint Framework is based on the source-notification model. 動的データ ソースになるコンポーネントは、データを提供し、その変更について通知します。Component designated as a dynamic data source, provides data and notifies about its changes. ページ上の他のコンポーネントは、動的データ ソースが発行した通知をサブスクライブできます。Other components on the page can subscribe to notifications issued by a dynamic data source. 通知を処理する場合、動的データ コンシューマーはデータ ソースが公開している動的データ セットの現在の値を取得できます。When handling notifications, dynamic data consumers can retrieve the current value of the dynamic data set exposed by the data source.

すべての動的なデータ ソースは、IDynamicDataCallables インターフェイスを実装します。Every dynamic data source implements the IDynamicDataCallables interface. 次に、今後のイベントのリストを表示する Web パーツの例を示します。Following, is an example of a web part that displays a list of upcoming events. 各イベントについて、名前、説明、場所などのいくつかの情報があります。For each event, it includes some information such as its name, description and location. イベント Web パーツは、選択されたイベントの情報をイベントに関する完全な情報と場所のアドレスという 2 つの方法でページの他のコンポーネントに公開します。The events web part exposes information about the selected event to other components on the page in two ways: the complete event information and the location address.

import { IDynamicDataPropertyDefinition, IDynamicDataCallables } from '@microsoft/sp-dynamic-data';

export default class EventsWebPart extends BaseClientSideWebPart<IEventsWebPartProps> implements IDynamicDataCallables {
  /**
   * Currently selected event
   */
  private _selectedEvent: IEvent;

  /**
   * Event handler for selecting an event in the list
   */
  private _eventSelected = (event: IEvent): void => {
    // store the currently selected event in the class variable. Required
    // so that connected component will be able to retrieve its value
    this._selectedEvent = event;
    // notify subscribers that the selected event has changed
    this.context.dynamicDataSourceManager.notifyPropertyChanged('event');
    // notify subscribers that the selected location has changed
    this.context.dynamicDataSourceManager.notifyPropertyChanged('location');
  }

  protected onInit(): Promise<void> {
    // register this web part as dynamic data source
    this.context.dynamicDataSourceManager.initializeSource(this);

    return Promise.resolve();
  }

  /**
   * Return list of dynamic data properties that this dynamic data source
   * returns
   */
  public getPropertyDefinitions(): ReadonlyArray<IDynamicDataPropertyDefinition> {
    return [
      {
        id: 'event',
        title: 'Event'
      },
      {
        id: 'location',
        title: 'Location'
      }
    ];
  }

  /**
   * Return the current value of the specified dynamic data set
   * @param propertyId ID of the dynamic data set to retrieve the value for
   */
  public getPropertyValue(propertyId: string): IEvent | ILocation {
    switch (propertyId) {
      case 'event':
        return this._selectedEvent;
      case 'location':
        return this._selectedEvent ? { city: this._selectedEvent.city, address: this._selectedEvent.address } : undefined;
    }

    throw new Error('Bad property id');
  }

  public render(): void {
    const element: React.ReactElement<IEventsProps> = React.createElement(
      Events,
      {
        displayMode: this.displayMode,
        onEventSelected: this._eventSelected,
        title: this.properties.title,
        updateProperty: (value: string): void => {
          this.properties.title = value;
        },
        siteUrl: this.context.pageContext.web.serverRelativeUrl
      }
    );

    ReactDom.render(element, this.domElement);
  }

  // ... omitted for brevity
}

重要

IDynamicDataCallables インターフェイスは、Web パーツと拡張機能だけでなく、どのクラスにも実装できます。The IDynamicDataCallables interface can be implemented by any class, not just web parts and extensions. 動的データ ソースが複雑なロジックを必要とする場合、ロジックを Web パーツまたは拡張機能の中に直接実装するのではなく、別のクラスに移動することを検討してください。If the dynamic data source requires complex logic, you should consider moving it into a separate class rather than implementing it directly inside a web part or extension.

IDynamicDataCallables インターフェイスを実装するクラスは、getPropertyDefinitionsgetPropertyValue の 2 つのメソッドを定義する必要があります。The class implementing the IDynamicDataCallables interface must define two methods: getPropertyDefinitions and getPropertyValue. getPropertyDefinitions メソッドは、特定の動的データ ソースが返すデータ型の配列を返します。The getPropertyDefinitions method returns an array of types of data that the particular dynamic data source returns. 前の例では、Web パーツはイベントとその場所に関する詳細情報を公開します。In the previous example, the web part exposes detailed information about an event and its location. 情報は 1 つのオブジェクト (_selectedEvent) からのものですが、2 つの異なるシェイプで公開すれば、Web パーツはより再利用が可能なものになり、イベントに固有ではない他の Web パーツと組み合わせて使用することができるようになります。たとえば、指定したアドレスの地図を表示できる地図 Web パーツなどです。Even though the information comes from a single object (_selectedEvent), by exposing it in two different shapes, the web part is more reusable and could be used in combination with other web parts that aren't specific to events, such as a map web part that can show a map for the specified address. Web パーツをデータ ソースに接続すると、データ ソースが公開するデータの種類のリストがエンドユーザーに表示されます。The list of the data types exposed by the data source is displayed to end-users when connecting web parts to the data source.

重要

たとえば次のように、getPropertyValue メソッドによって返されるオブジェクトはフラットでなければなりません。The object returned by the getPropertyValue method should be flat, for example:

{
   "date": "2018-06-01T11:21:59.446Z",
   "name": "Tampa Home Show",
   "organizerEmail": "Grady Archie",
   "organizerName": "GradyA@contoso.onmicrosoft.com"
}

入れ子構造を持つオブジェクトは、シリアル化の際にフラットにされますが、望ましくない影響が現われる可能性があります。Object with a nested structure will be flattened during serialization, which could lead to undesired effects. たとえば、次のようなオブジェクトは、For example, object like:

{
   "date": "2018-06-01T11:21:59.446Z",
   "name": "Tampa Home Show",
   "organizer": {
      "email": "Grady Archie",
      "name": "GradyA@contoso.onmicrosoft.com"
   }
}

シリアル化後には、次のようになります。would after serialization become:

{
   "date": "2018-06-01T11:21:59.446Z",
   "name": "Tampa Home Show",
   "organizer.email": "Grady Archie",
   "organizer.name": "GradyA@contoso.onmicrosoft.com"
}

getPropertyValue メソッドは、特定のデータ型の値を返します。The getPropertyValue method returns the value for the particular type of data. propertyId 引数の値は、getPropertyDefinitions メソッドで指定された定義の id に対応します。The value of the propertyId argument corresponds to the id of the definition specified in the getPropertyDefinitions method.

動的データ ソースとしてコンポーネントを登録するには、this.context.dynamicDataSourceManager.initializeSource() メソッドを呼び出し、動的なデータ ソースのインスタンスをパラメーターとして渡します。To register a component as a dynamic data source, call the this.context.dynamicDataSourceManager.initializeSource() method, passing the instance of the dynamic data source as a parameter. 前の例で、Web パーツ自体が IDynamicDataCallables インターフェイスを実装しているため、initializeSource メソッドは this を引数として呼び出されます。In the previous example, the web part itself implements the IDynamicDataCallables interface, which is why the initializeSource method is called with this as its argument.

サンプル コードでは、Web パーツが今後のイベントをリストにして表示します。In the example code, the web part displays upcoming events in a list. ユーザーがリストからイベントを選択するたびに、Web パーツは _eventSelected メソッドを呼び出します。Each time, the user selects an event from the list, the web part calls the _eventSelected method. そのメソッドでは、Web パーツは選択したイベントを _selectedEvent クラス変数に割り当て、選択されているイベントと場所に関する情報が変更されたことを示す通知を、変更されたデータ セットを示す定義の id を渡して this.context.dynamicDataSourceManager.notifyPropertyChanged() メソッドを呼び出すことにより発行します。In that method, the web part assigns the selected event to the _selectedEvent class variable and issues a notification that the information about the selected event and location has changed by calling the this.context.dynamicDataSourceManager.notifyPropertyChanged() method passing the id of the definition that represents the changed data set.

Web パーツでの動的データの使用Consume dynamic data in web parts

Web パーツは、ページに存在する動的データ ソースによって公開されるデータを使用できます。Web parts can consume data exposed by dynamic data sources present on the page. 前のイベント リスト Web パーツで選択されたイベントの場所を地図上で表示する Web パーツのコードを次に示します。Following is the code of a web part showing on a map the location of the event selected in the events list web part showed previously.

import { DynamicProperty } from '@microsoft/sp-component-base';

/**
 * Map web part properties
 */
export interface IMapWebPartProps {
  /**
   * The address to display on the map
   */
  address: DynamicProperty<string>;
  /**
   * Bing maps API key to use with the Bing maps API
   */
  bingMapsApiKey: string;
  /**
   * The city where the address is located
   */
  city: DynamicProperty<string>;
  /**
   * Web part title
   */
  title: string;
}

/**
 * Map web part. Shows the map of the specified location. The location can be
 * specified either directly in the web part properties or via a dynamic data
 * source connection.
 */
export default class MapWebPart extends BaseClientSideWebPart<IMapWebPartProps> {
  /**
   * Event handler for clicking the Configure button on the Placeholder
   */
  private _onConfigure = (): void => {
    this.context.propertyPane.open();
  }

  public render(): void {
    // Get the location to show on the map. The location will be retrieved
    // either from the event selected in the connected data source or from the
    // address entered in web part properties
    const address: string | undefined = this.properties.address.tryGetValue();
    const city: string | undefined = this.properties.city.tryGetValue();
    const needsConfiguration: boolean = !this.properties.bingMapsApiKey || (!address && !this.properties.address.tryGetSource()) || 
    (!city && !this.properties.city.tryGetSource());

    const element: React.ReactElement<IMapProps> = React.createElement(
      Map,
      {
        needsConfiguration: needsConfiguration,
        httpClient: this.context.httpClient,
        bingMapsApiKey: this.properties.bingMapsApiKey,
        dynamicAddress: !!this.properties.address.tryGetSource(),
        address: `${address} ${city}`,
        onConfigure: this._onConfigure,
        width: this.domElement.clientWidth,
        height: this.domElement.clientHeight,
        title: this.properties.title,
        displayMode: this.displayMode,
        updateProperty: (value: string): void => {
          this.properties.title = value;
        }
      }
    );

    ReactDom.render(element, this.domElement);
  }

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

  protected get propertiesMetadata(): IWebPartPropertiesMetadata {
    return {
      // Specify the web part properties data type to allow the address
      // information to be serialized by the SharePoint Framework.
      'address': {
        dynamicPropertyType: 'string'
      },
      'city': {
        dynamicPropertyType: 'string'
      }
    };
  }

  protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
    return {
      pages: [
        {
          groups: [
            {
              groupName: strings.BingMapsGroupName,
              groupFields: [
                PropertyPaneTextField('bingMapsApiKey', {
                  label: strings.BingMapsApiKeyFieldLabel
                }),
                PropertyPaneLink('', {
                  href: 'https://www.bingmapsportal.com/',
                  text: strings.GetBingMapsApiKeyLinkText,
                  target: '_blank'
                })
              ]
            },
            // Web part properties group for specifying the information about
            // the address to show on the map.
            {
              // Primary group is used to provide the address to show on the map
              // in a text field in the web part properties
              primaryGroup: {
                groupName: strings.DataGroupName,
                groupFields: [
                  PropertyPaneTextField('address', {
                    label: strings.AddressFieldLabel
                  }),
                  PropertyPaneTextField('city', {
                    label: strings.CityFieldLabel
                  })
                ]
              },
              // Secondary group is used to retrieve the address from the
              // connected dynamic data source
              secondaryGroup: {
                groupName: strings.DataGroupName,
                groupFields: [
                  PropertyPaneDynamicFieldSet({
                    label: 'Address',
                    fields: [
                      PropertyPaneDynamicField('address', {
                        label: strings.AddressFieldLabel
                      }),
                      PropertyPaneDynamicField('city', {
                        label: strings.CityFieldLabel
                      })
                    ],
                    sharedConfiguration: {
                      depth: DynamicDataSharedDepth.Property
                    }
                  })
                ]
              },
              // Show the secondary group only if the web part has been
              // connected to a dynamic data source
              showSecondaryGroup: !!this.properties.address.tryGetSource()
            } as IPropertyPaneConditionalGroup
          ]
        }
      ]
    };
  }

  protected get disableReactivePropertyChanges(): boolean {
    // set property changes mode to reactive, so that the Bing Maps API is not
    // called on each keystroke when typing in the address to show on the map
    // in web part properties
    return true;
  }
}

SharePoint Framework には、Web パーツを動的データ ソースに接続するための標準的な UI が用意されています。SharePoint Framework offers standard UI for connecting web parts to dynamic data sources. この UI を使用すると、使用可能な動的データ ソースとそのプロパティを検出し、構成されている接続を保持することにより、動的データの操作が簡単になります。This UI simplifies working with dynamic data by discovering available dynamic data sources and their properties and persisting the configured connection. この UI を使用するには、動的データを使用する Web パーツにいくつかの特定の文書パーツを含める必要があります。To use this UI, a web part that consumes dynamic data must include a few specific building blocks.

動的 Web パーツのプロパティを定義するDefine dynamic web part properties

各 Web パーツのプロパティは、動的データ ソースからデータを取得でき、DynamicProperty<T> として定義する必要があります。ここで、T の種類は、次のように、プロパティに格納されるデータの種類を示します。Each web part property, for which the data can be retrieved from a dynamic data source, should be defined as DynamicProperty<T> where the T type denotes the type of data stored in the property, for example:

/**
 * Map web part properties
 */
export interface IMapWebPartProps {
  /**
   * The address to display on the map
   */
  address: DynamicProperty<string>;

  // ... omitted for brevity
}

この例では、アドレスは文字列ですが、ブール値、数値、またはオブジェクトなどの他の種類のデータもサポートします。In this example, the address is a string, but other types of data such as boolean, numbers or objects are supported as well. DynamicProperty として定義されている Web パーツのプロパティは自分のデータを、動的データ ソースから取得することも、Web パーツのプロパティに直接入力された値から取得することもできます。Web part properties defined as DynamicProperty can retrieve their data from dynamic data sources or values provided directly in the web part properties. 同じ Web パーツのプロパティを、Web パーツのプロパティに構成される動的データ ソースと静的な値の両方に使用できるため、複数の Web パーツのプロパティを定義する必要はなく、さまざまな Web パーツの構築が簡略化されます。Because the same web part property can be used for both dynamic data sources and static values configured in web part properties, you don't need to define multiple web part properties what simplifies building versatile web parts.

動的プロパティに格納されるデータの種類の定義Define the type of data stored in dynamic properties

動的プロパティごとに、保持するデータの種類を指定する必要があります。For each dynamic property you have to specify the type of data it holds. これは、ページに追加する Web パーツのインスタンスが正しくシリアル化できるようにするために必要です。This is necessary, so that the instance of the web part added to a page can be properly serialized. 各動的 Web パーツのプロパティについて、propertiesMetadata get アクセス操作子で dynamicPropertyType 値を指定します。For each dynamic web part property, in the propertiesMetadata getter, specify the dynamicPropertyType value:

protected get propertiesMetadata(): IWebPartPropertiesMetadata {
  return {
    // Specify the web part properties data type to allow the address
    // information to be serialized by the SharePoint Framework.
    'address': {
      dynamicPropertyType: 'string'
    },
    'city': {
      dynamicPropertyType: 'string'
    }
  };
}

dynamicPropertyType プロパティの値は、booleannumberstringarrayobject にすることができます。Possible values for the dynamicPropertyType property are: boolean, number, string, array and object.

Web パーツを動的データ ソースに接続するための標準的な UI の使用Use the standard UI for connecting web part to dynamic data sources

ユーザーが Web パーツをページで使用可能な動的データ ソースに接続できるようにするため、SharePoint Framework には Web パーツのプロパティ ウィンドウからアクセスできる標準的な UI が用意されています。To allow users to connect web parts to dynamic data sources available on the page, SharePoint Framework provides a standard UI which can be accessed from the web part property pane.

SharePoint Framework Web パーツをページで使用できる動的データ ソースに接続するための標準的な UI

重要

Web パーツを動的データ ソースに接続する標準的な UI を使用する際、動的データ ソースが特定の動的プロパティの値 (前の例では、イベントのリストで選択されているイベント) を返すことを確認してください。When using the standard UI to connect a web part to a dynamic data source, ensure, that the dynamic data source returns a value for the given dynamic property (in the previous example, there is an event selected in the list of events). 返さない場合、UI はデータ ソースによって返されるデータの種類を確認できず、接続の設定は失敗します。If it doesn't, the UI will not be able to determine the type of data returned by the data source and setting up the connection will fail.

最も簡単な形態では、UI を次のように定義できます。In its simplest form, the UI could be defined as follows:

protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
  return {
    pages: [
      {
        groups: [
          {
            groupFields: [
              PropertyPaneDynamicFieldSet({
                label: 'Select event source',
                fields: [
                  PropertyPaneDynamicField('event', {
                    label: 'Event source'
                  })
                ]
              })
            ]
          }
        ]
      }
    ]
  };
}

動的プロパティのセットごとに、PropertyPaneDynamicFieldSet メソッドを使用して新しいグループを追加します。For each set of dynamic properties, add a new group using the PropertyPaneDynamicFieldSet method. 各動的 Web パーツのプロパティについて、PropertyPaneDynamicField を追加します。こうすると、ユーザーは PropertyPaneDynamicField で指定された Web パーツのプロパティがそのデータをどのプロパティから取得するかを選択できます。For each dynamic web part property, add a PropertyPaneDynamicField, which will allow users to select from which property, the web part property specified in the PropertyPaneDynamicField should retrieve its data.

動的データ フィールド セットが複数の動的プロパティで構成される場合、sharedConfiguration.depth プロパティを使用して接続データを共有する方法を指定できます。If your dynamic data field set consists of multiple dynamic properties, you can specify how the connection data is shared using the sharedConfiguration.depth property:

groupFields: [
  PropertyPaneDynamicFieldSet({
    label: 'Address',
    fields: [
      PropertyPaneDynamicField('address', {
        label: strings.AddressFieldLabel
      }),
      PropertyPaneDynamicField('city', {
        label: strings.CityFieldLabel
      })
    ],
    sharedConfiguration: {
      depth: DynamicDataSharedDepth.Property
    }
  })
]

この例では、すべての動的プロパティが、選択した接続およびプロパティを共有します。In this example, all dynamic properties share the selected connection and property. これは、データ ソースによって公開される選択したプロパティがオブジェクトであり、選択したオブジェクトの別の複数のプロパティに動的プロパティを接続する場合に便利です。This is useful in cases, where the selected property exposed by the data source is an object and you want to connect your dynamic properties to the different properties of the selected object. 同じデータ ソースを使用するものの、選択したデータ ソースが公開する別のプロパティに各 Web パーツのプロパティを接続する場合は、代わりに DynamicDataSharedDepth.Source を使用できます。If you want to use the same data source, but connect each web part property to a different property exposed by the selected data source, you can use DynamicDataSharedDepth.Source instead. 最後に、各プロパティが別のデータ ソースからデータを取得する場合は、sharedConfiguration.depth プロパティを DynamicDataSharedDepth.None に設定します。Finally, if you want each property to retrieve its data from a different data source, you can set the sharedConfiguration.depth property to DynamicDataSharedDepth.None.

動的データを使用するか自分で値を指定するかユーザーが選択できるようにするAllow users to choose if they want to use dynamic data or specify the value themselves

Web パーツを作成するときに、ユーザーが Web パーツをページのその他のコンポーネントに接続できるようにすることも、自分で Web パーツのプロパティの値を指定できるようにすることもできます。When building web parts, you can allow users to connect web parts to other components on the page, or specify values of web part properties themselves. これを行うのに必要な労力はほんのわずかに過ぎませんが、広範囲の用途に適したさまざまな Web パーツを作成できます。This requires very little additional effort and allows you to build web parts that are more versatile and suitable for a broader range of use cases.

動的プロパティからデータを読み込むか Web パーツのプロパティに自分で値を入力するかをユーザーが選択できるようにするには、Web パーツのプロパティのグループを IPropertyPaneConditionalGroup グループとして定義します。To allow users to be able to choose if they want to load data from a dynamic property or enter the value themselves in the web part properties, you can define the web part properties group as a IPropertyPaneConditionalGroup group.

protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
  return {
    pages: [
      {
        groups: [
          // Web part properties group for specifying the information about
          // the address to show on the map.
          {
            // Primary group is used to provide the address to show on the map
            // in a text field in the web part properties
            primaryGroup: {
              groupName: strings.DataGroupName,
              groupFields: [
                PropertyPaneTextField('address', {
                  label: strings.AddressFieldLabel
                }),
                PropertyPaneTextField('city', {
                  label: strings.CityFieldLabel
                })
              ]
            },
            // Secondary group is used to retrieve the address from the
            // connected dynamic data source
            secondaryGroup: {
              groupName: strings.DataGroupName,
              groupFields: [
                PropertyPaneDynamicFieldSet({
                  label: 'Address',
                  fields: [
                    PropertyPaneDynamicField('address', {
                      label: strings.AddressFieldLabel
                    }),
                    PropertyPaneDynamicField('city', {
                      label: strings.CityFieldLabel
                    })
                  ],
                  sharedConfiguration: {
                    depth: DynamicDataSharedDepth.Property
                  }
                })
              ]
            },
            // Show the secondary group only if the web part has been
            // connected to a dynamic data source
            showSecondaryGroup: !!this.properties.address.tryGetSource()
          } as IPropertyPaneConditionalGroup
        ]
      }
    ]
  };
}

条件付き Web パーツのプロパティ ウィンドウのグループには、プライマリ グループとセカンダリ グループがあります。A conditional web part property pane group consists of a primary and a secondary group. showSecondaryGroup プロパティを使用すると、セカンダリ グループを表示してプライマリ グループを非表示にするするタイミングを指定できます。Using the showSecondaryGroup property, you can specify when the secondary group should be visible and the primary group should be hidden. 上記の例では、ユーザーが省略記号 (...) をクリックして Web パーツを動的データ ソースに接続することを選択すると、Web パーツを動的データ ソースに接続するために使用するセカンダリ グループが表示されます。In the example above, the secondary group, which is used for connecting the web part to a dynamic data source, will be visible when the user selected to connect the web part to a dynamic data source by clicking the ellipsis (...).

SharePoint Framework の Web パーツを動的データ ソースに接続するために使用する Web パーツのプロパティ ウィンドウで省略記号に置かれたマウス ポインター

考慮事項Considerations

  • 各ページは、複数の動的データ ソースやコンシューマーを持つことができるeach page can have multiple dynamic data sources and consumers
  • 各コンポーネントは、他のコンポーネントに動的データを提供することも、他のコンポーネントの動的データを使用することもできるeach component can both provide dynamic data to other components and consume dynamic data from other components
  • コンポーネントは、複数の動的データ ソースからのデータを使用できるcomponents can consume data from multiple dynamic data sources
  • SharePoint Framework は、Web パーツをデータ ソースに接続するための標準的な UI を提供し、接続情報を自動的に保持するSharePoint Framework offers standard UI for connecting web parts to data sources and automatically persists connection information

関連項目See also