高级卡片视图功能

本教程以下列教程为基础: 生成第一个 SharePoint 自适应卡片扩展

重要

此功能在 1.14 版本中仍处于预览状态,不应在生产中使用。 我们正在考虑在即将发布的 1.15 版本中正式发布它们。

在本教程中将实现高级卡视图功能。 你将继续上一教程,并创建一个由 SharePoint 列表中的数据提供支持的卡片视图。

创建测试列表

准备本教程时,在 SharePoint 站点中创建一个包含一些示例数据的新列表:

  1. 浏览到网站,并创建名为“指令列表”的新列表。

  2. 添加名为 “说明”“单行文本” 列。

    空 SharePoint 列表

  3. 将几个项添加到列表中:

    • 标题: 步骤 1,说明: 使用 ACE
    • 标题: 步骤 2,说明: ???
    • 标题: 步骤 3,说明: SPFx 🚀 🌝
  4. 获取列表 ID:

    1. 查看列表时,选择套件栏中的 齿轮 图标,打开 设置 菜单。 然后选择 “列表设置” 菜单项:

      列表设置屏幕

    2. “列表设置” 页上,在 URL 中定位列表的 ID:

      URL 中的列表 ID

    3. 保存列表的 ID,以便可以在下一步中使用它。

添加 ACE 功能

从上一教程中的 HelloWorld ACE 开始,生成第一个 SharePoint 自适应卡扩展。 在准备步骤 2 时进行以下更新。

更改属性

让我们修改 ACE 的属性,并设置包含 ACE 将显示的数据的列表 ID:

  1. 在项目中定位并打开以下文件: ./src/adaptiveCardExtensions/helloWorld/HelloWorldAdaptiveCardExtension.ts

  2. 更新用于定义 ACE 属性类型的接口 properties:

    export interface IHelloWorldAdaptiveCardExtensionProps {
      title: string;
      description: string;
      iconProperty: string;
      listId: string;
    }
    
  3. 在项目中定位并打开以下文件: ./src/adaptiveCardExtensions/helloWorld/HelloWorldAdaptiveCardExtension.manifest.json

  4. 通过设置以下 preConfiguredEntries,使用上一步骤中创建的列表 ID 初始化 ACE:

      "preconfiguredEntries": [{
        // ...
        "properties": {
          "title": "HelloWorld",
          "description": "HelloWorld description",
          "iconProperty": "", // Default to sharepointlogo
          "listId": "" // TODO: enter list id
        }
      }]
    

    重要

    请确保将之前获取的列表的 ID 输入到上面的 preconfiguredEntries 代码中的 listId 属性中。

  5. 在项目中定位并打开以下文件: ./src/adaptiveCardExtensions/helloWorld/HelloWorldPropertyPane.ts

  6. 通过添加以下字段更新“属性窗格”:

    PropertyPaneTextField('listId', {
      label: 'List ID'
    })
    

更改 ACE 的状态

接下来,我们来更新 ACE 的状态。 状态更改时将触发 ACE 进行重新呈现。 这些更改将列表项集合添加到状态以及当前所显示的项目,如你将要添加的 currentIndex 属性所指示。

  1. 在项目中定位并打开以下文件: ./src/adaptiveCardExtensions/helloWorld/HelloWorldAdaptiveCardExtension.ts

  2. 通过在文件中添加以下代码,为“列表数据”添加新接口:

    export interface IListItem {
      title: string;
      description: string;
    }
    
  3. 更新用于定义 ACE 状态的接口,以使用新的 IListItem 接口:

    export interface IHelloWorldAdaptiveCardExtensionState {
      currentIndex: number;
      items: IListItem[];
    }
    
  4. 通过更新 ACE 中的 onInit() 方法来更新 state 初始化:

    public onInit(): Promise<void> {
      this.state = {
        currentIndex: 0,
        items: []
      };
      // ...
    }
    
  5. 通过更新 onPropertyPaneFieldChanged() 方法,暂时删除 ACE 和视图中引用 state 的位置:

    // tslint:disable-next-line: no-any
    protected onPropertyPaneFieldChanged(propertyPath: string, oldValue: any, newValue: any): void {
    }
    
  6. 在项目中定位并打开以下文件: ./src/adaptiveCardExtensions/helloWorld/quickView/QuickView.ts

  7. data()onAction() 方法更新为以下内容:

    public get data(): IQuickViewData {
      return {
        subTitle: '',
        title: strings.Title
      };
    }
    
    public onAction(action: IActionArguments): void {
    }
    

现在,状态已更新,我们可以更新 ACE 以从 SharePoint 列表中提取数据。

添加依赖项

下一步是添加对项目和 ACE 的支持,以从 SharePoint 列表检索项目。 为此,你将使用 SharePoint 框架 (SPFx) API 以调用 SharePoint REST 终结点。

首先,向用于向 REST 终结点提交 HTTP 请求的 SPFx 包添加依赖项:

  1. 在项目中找到并打开以下文件: ./package.json。 请注意 package.json 文件的 dependencies 节中作为依赖关系的其他软件包所使用的 SPFx 相关的 beta 版。

  2. 在项目中安装以下 NPM 包:@microsoft/sp-http

    npm install @microsoft/sp-http -SE
    

提取列表数据

接下来,添加对调用 SharePoint REST API 以及将检索到的项目添加到 ACE 状态的支持。 状态更新时将触发 ACE 进行重新呈现。

  1. 在项目中定位并打开以下文件: ./src/adaptiveCardExtensions/helloWorld/HelloWorldAdaptiveCardExtension.ts

  2. 使用 SPFx SPHttpClient API 请求列表数据。 将以下内容添加到实现 ACE 的类:

    import { SPHttpClient } from '@microsoft/sp-http';
    
    ..
    
    private _fetchData(): Promise<void> {
      if (this.properties.listId) {
        return this.context.spHttpClient.get(
          `${this.context.pageContext.web.absoluteUrl}` +
            `/_api/web/lists/GetById(id='${this.properties.listId}')/items`,
          SPHttpClient.configurations.v1
        )
          .then((response) => response.json())
          .then((jsonResponse) => jsonResponse.value.map(
            (item) => { return { title: item.Title, description: item.Description }; })
            )
          .then((items) => this.setState({ items }));
      }
    
      return Promise.resolve();
    }
    
  3. 通过更新 onInit() 方法,更新 ACE 以在初始化列表数据期间请求列表数据。

    如下所示,将最后一行 return Promise.resolve(); 替换为 return this._fetchData();

    public onInit(): Promise<void> {
      // ...
      return this._fetchData();
    }
    
  4. 更新 ACE,以便在更新属性窗格时请求提供列表数据。 在实现 ACE 类中添加以下方法。 此代码仅在属性窗格中更改列表的 ID 时才请求数据:

    protected onPropertyPaneFieldChanged(propertyPath: string, oldValue: any, newValue: any): void {
      if (propertyPath === 'listId' && newValue !== oldValue) {
        if (newValue) {
          this._fetchData();
        } else {
          this.setState({ items: [] });
        }
      }
    }
    

卡片更新

更新 ACE 以从 SharePoint 列表中提取项目后,我们来更新卡片以显示此数据。

  1. 在项目中定位并打开以下文件: ./src/adaptiveCardExtensions/helloWorld/cardView/CardView.ts

  2. 更新 data() getter 以显示列表中的数据:

    public get data(): IPrimaryTextCardParameters {
      const { title, description } = this.state.items[this.state.currentIndex];
      return {
        description,
        primaryText: title
      };
    }
    

现在可以测试 ACE。 在托管工作台中生成并启动 ACE:

gulp serve

加载本地 Web 服务器后,导航到托管的工作台: https://{tenant}.sharepoint.com/_layouts/15/workbench.aspx

注意

从工作台中删除所有旧的 ACE 实例。 上一教程 中的 ACE 实例将显示一个错误信息,因为 ACE 属性已更新。

打开工具箱并选择 ACE:

从工具箱中选择 ACE

条件卡片视图

默认情况下,视图会自动调整卡片的大小。 然而,ACE 可以选择为任何给定卡片的尺寸提供不同的视图。

更改 HelloWorld ACE,以显示 “中等 卡片”大小中的“列表项总数”,并在 卡大小中显示“列表项”,以最大程度地使用可用空间。

中型卡片视图

让我们为 ACE 创建一个中型卡片视图:

  1. 在文件夹创建一个新文件 ./src/adaptiveCardExtensions/helloWorld/cardView/MediumCardView.ts

  2. 添加以下代码以创建新的 中型 卡视图:

    import {
      BaseBasicCardView,
      IActionArguments,
      IBasicCardParameters,
      ICardButton
    } from '@microsoft/sp-adaptive-card-extension-base';
    import {
      IListItem, QUICK_VIEW_REGISTRY_ID,
      IHelloWorldAdaptiveCardExtensionProps,
      IHelloWorldAdaptiveCardExtensionState
    } from '../HelloWorldAdaptiveCardExtension';
    
    // Extend from BaseBasicCardView
    export class MediumCardView extends BaseBasicCardView<IHelloWorldAdaptiveCardExtensionProps, IHelloWorldAdaptiveCardExtensionState> {
      // Use the Card button to open the Quick View
      public get cardButtons(): [ICardButton] {
        return [
          {
            title: 'View All',
            action: {
              type: 'QuickView',
              parameters: {
                view: QUICK_VIEW_REGISTRY_ID
              }
            }
          }
        ];
      }
    
      // Display the total number of steps
      public get data(): IBasicCardParameters {
        return {
          primaryText: `${this.state.items.length} Steps`
        };
      }
    }
    
  3. 在项目中定位并打开以下文件: ./src/adaptiveCardExtensions/helloWorld/HelloWorldAdaptiveCardExtension.ts

  4. 现在,通过对 ACE 进行以下更改来注册新视图:

    import { MediumCardView } from './cardView/MediumCardView';
    
    ..
    
    const MEDIUM_VIEW_REGISTRY_ID: string = 'HelloWorld_MEDIUM_VIEW';
    
    ..
    
    public onInit(): Promise<void> {
      // ...
      this.cardNavigator.register(CARD_VIEW_REGISTRY_ID, () => new CardView());
      this.cardNavigator.register(MEDIUM_VIEW_REGISTRY_ID, () => new MediumCardView());
      // ...
    }
    
  5. 更新 renderCard() 方法,以根据卡片大小返回 中等 卡视图或 大型 卡视图:

    protected renderCard(): string | undefined {
      return this.cardSize === 'Medium' ? MEDIUM_VIEW_REGISTRY_ID : CARD_VIEW_REGISTRY_ID;
    }
    

通过刷新工作台测试更改:

更新的 ACE 呈现不同大小的 ACE

将卡片大小更改为 大型 并刷新浏览器:

ACE 卡呈现“大型卡”

大型卡片交互性

ACE 卡视图支持用户交互。 按钮可以调用 REST API,也可以用于通过其他方式与卡片交互。 在本部分中,将更改“大型卡”视图以循环访问 SharePoint 列表中的项。

  1. 在项目中定位并打开以下文件: ./src/adaptiveCardExtensions/helloWorld/cardView/CardView.ts

  2. 在文件顶部,将 IActionArguments 添加为要从 @microsoft/sp-adaptive-card-extension-base 包导入的引用之一:

    import { IActionArguments } from '@microsoft/sp-adaptive-card-extension-base';
    
  3. 卡片视图上的按钮可以根据 ACE 的当前状态进行动态调整。 将以下代码添加到 ACE 的 CardView.ts 文件:

    public get cardButtons(): [ICardButton] | [ICardButton, ICardButton] {
      const buttons: ICardButton[] = [];
    
      // Hide the Previous button if at Step 1
      if (this.state.currentIndex > 0) {
        buttons.push({
          title: 'Previous',
          action: {
            type: 'Submit',
            parameters: {
              id: 'previous',
              op: -1 // Decrement the index
            }
          }
        });
      }
    
      // Hide the Next button if at the end
      if (this.state.currentIndex < this.state.items.length - 1) {
        buttons.push({
          title: 'Next',
          action: {
            type: 'Submit',
            parameters: {
              id: 'next',
              op: 1 // Increment the index
            }
          }
        });
      }
    
      return buttons as [ICardButton] | [ICardButton, ICardButton];
    }
    
  4. 接下来,通过实现以下方法,在选择按钮时更新 state:

    public onAction(action: IActionArguments): void {
      if (action.type === 'Submit') {
        const { id, op } = action.data;
        switch (id) {
          case 'previous':
          case 'next':
          this.setState({ currentIndex: this.state.currentIndex + op });
          break;
        }
      }
    }
    

通过在浏览器中重新加载工作台来测试更改。

卡的第一个实例将显示第一个带有 “下一项” 按钮的列表项:

带有“下一步”按钮的卡的第一视图

选择 “下一步” 按钮。 卡片将在列表中显示下一项,并添加 “上一步” 按钮:

显示既不是列表中第一项也不是最后一项的 SharePoint 列表项的卡

选择 “下一个” 按钮,直到到达列表中的最后一项。 卡片将显示列表中的项,并且仅显示“ 上一步 ”按钮:

显示列表中最后一个项目的卡片,其中只有一个“上一步”按钮

缓存卡片视图和 ACE 状态

从 SPFx v1.14 开始,AES 具有可配置为存储的客户端缓存层:

  1. 最新呈现的卡片。
  2. ACE 的状态。

从缓存的卡片视图呈现

如果存储了最新呈现的卡片,仪表板会在初始化 ACE 之前呈现此缓存的卡片,从而提高感知性能。

可以通过替代以下方法配置此缓存的设置:

protected getCacheSettings(): Partial<ICacheSettings> {
  return {
    isEnabled: true, // can be set to false to disable caching
    expiryTimeInSeconds: 86400, // controls how long until the cached card and state are stale
    cachedCardView: () => new CardView() // function that returns the custom Card view that will be used to generate the cached card
  };
}

从缓存的 ACE 状态解除冻结

可以通过替代以下方法配置缓存的 ACE 状态子集:

protected getCachedState(state: TState): Partial<TState>;

此方法返回的对象将被序列化并缓存。 默认情况下,不缓存任何状态。 在下次调用 onInit 时,反序列化值将作为 ICachedLoadParameters 的一部分传递到 onInit

public onInit(cachedLoadParameters?: ICachedLoadParameters): Promise<void>;

然后,该值可用于解除冻结新初始化的 ACE 的状态。

结束语

经过该实验后,应熟悉以下内容:

  • 更改 ACE 的默认 properties
  • 更改 ACE properties/state 接口
  • 创建和注册卡片视图
  • 有条件地呈现卡片视图元素
  • 高级卡片视图操作
  • 缓存卡片视图和 ACE 状态